c++ - 给定曲线和私有(private)指数创建 ECDSA 私钥?

标签 c++ private-key crypto++ ecdsa signer

我是 cryptopp 的新手,并且一直在努力创建用于 ECDSA 签名的私钥。

我有一个十六进制编码的私有(private)指数 E4A6CFB431471CFCAE491FD566D19C87082CF9FA7722D7FA24B2B3F5669DBEFB。这存储为字符串。

我想用它来使用 ECDSA 对文本 block 进行签名。我的代码看起来有点像这样

string Sig::genSignature(const string& privKeyIn, const string& messageIn)
{
   AutoSeededRandomPool prng;
   ECDSA<ECP, SHA256>::PrivateKey privateKey;
   privateKey.AccessGroupParameters().Initialize(ASN1::secp256r1());
   privateKey.Load(StringSource(privKeyIn, true, NULL).Ref());
   ECDSA<ECP, SHA256>::Signer signer(privateKey);

   // Determine maximum size, allocate a string with that size
   size_t siglen = signer.MaxSignatureLength();
   string signature(siglen, 0x00);

   // Sign, and trim signature to actual size
   siglen = signer.SignMessage(prng, (const byte *) messageIn.data(), (size_t) messageIn.length(),       (byte*)signature.data());
   signature.resize(siglen);
   cout << signature.data() << endl;
   return signature;
}

当我尝试执行 privateKey.load(...) 时,此代码在 Visual Studio 中生成以下错误

First-chance exception at 0x7693C42D in DLLTest.exe: Microsoft C++ exception: CryptoPP::BERDecodeErr at memory location 0x0033EEA8.
Unhandled exception at 0x7693C42D in DLLTest.exe: Microsoft C++ exception: CryptoPP::BERDecodeErr at memory location 0x0033EEA8.

我猜我正在做一些有点愚蠢的事情......任何帮助都会很棒???

PS 我在使用 ECDH 生成 GMAC 时遇到了类似的问题,但通过将 key 保存为 SECByteBlock 来解决这个问题,但这个“技巧”在这种情况下似乎不起作用。

最佳答案

DLLTest.exe: Microsoft C++ exception: CryptoPP::BERDecodeErr ...

您有一个私有(private)指数,不是一个私钥。所以你应该对其调用Load。这导致了 Crypto++ BERDecodeErr 异常。

答案详见ECDSA wiki page ,但它并不明显。您需要执行以下操作以在给定曲线和指数的情况下初始化 privateKey::

string exp = "E4A6CFB431471CFCAE491FD566D19C87082CF9FA7722D7FA24B2B3F5669DBEFB";
exp.insert(0, "0x");

Integer x(exp.c_str());
privateKey.Initialize(ASN1::secp256r1(), x);

"0x" 之前确保 Integer 类将正确解析 ASCII 字符串。您还可以将 "h" 字符附加到字符串。您可以在 Integer.cpp 查看 Integer 类的解析代码StringToInteger 函数中的第 2960 行左右。


这是做同样事情的另一种方法:

string exp = "E4A6CFB431471CFCAE491FD566D19C87082CF9FA7722D7FA24B2B3F5669DBEFB";

HexDecoder decoder;
decoder.Put((byte*)exp.data(), exp.size());
decoder.MessageEnd();

Integer x;
x.Decode(decoder, decoder.MaxRetrievable());

privateKey.Initialize(ASN1::secp256r1(), x);

HexDecoder将为您执行 ASCII 到二进制的转换。 HexDecoder 持有的缓冲区随后将被 Integer 使用其 Decode (BufferedTransformation &bt, size_t inputLen, Signedness=UNSIGNED) 消耗。方法。


这是使用 HexDecoder 的另一种方式(Crypto++ 有时和脚本语言一样糟糕:)...

string exp = "E4A6CFB431471CFCAE491FD566D19C87082CF9FA7722D7FA24B2B3F5669DBEFB";
StringSource ss(exp, true /*punpAll*/, new HexDecoder);

Integer x;
x.Decode(ss, ss.MaxRetrievable());

privateKey.Initialize(ASN1::secp256r1(), x);

初始化 key 后,您应该验证它:

bool result = privateKey.Validate( prng, 3 );
if( !result ) { /* Handle error */ }

这将输出二进制数据:

cout << signature.data() << endl;

如果你想要一些可打印/可读的东西,通过 Crypto++ 运行它 HexEncoder .

关于c++ - 给定曲线和私有(private)指数创建 ECDSA 私钥?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27232053/

相关文章:

c++ - 调用线程会在 thread.join() 之后看到对局部变量的修改吗?

c++ - 如何编译 C++ 代码以在网页中显示(如在 PHP 中)

ssl - 从 GeoTrust 的两个证书生成 X.509 或 PEM 和私钥(RSA、PEM)

c++ - 未定义对 CryptoPP::AlignedAllocate(unsigned int) 的引用

c++ - Crypto++ 中的 PBKDF

c++ - 在 Qt 列表中存储来自数据库的查询结果的更好方法

c++ - 指针删除崩溃

linux - 在 macOS 上将 .pem 转换为 .ppk

ssl - 将 .pem 转换为 .crt 和 .key

c++ - 我正在使用 Crypto++ 进行 RSA 加密。我的纯文本超过了 FixedMaxPlaintextLength。我应该怎么办?