当前位置: 首页 > 知识库问答 >
问题:

给定曲线和私有指数的ECDSA私钥的创建?

东郭承业
2023-03-14

我是新到cryptopp,并一直在努力为ECDSA签名创建私钥。

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

我想用它来使用ECDSA签署文本块。我的代码看起来有点像这样

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;
}

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

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我在GMAC一代中使用ECDH时遇到了类似的问题,但是通过将密钥保存为SECByteBlock解决了这个问题,但是这个“技巧”在这种情况下似乎不起作用。

共有2个答案

韩安顺
2023-03-14

对于以后寻找此内容的其他人

string genSignature(const string& privKeyIn, const string& messageIn)
{
    CryptoPP::Integer secretNumber(genSecretNumber(privKeyIn, messageIn));
    AutoSeededRandomPool secretNumberGenerator;

    if (encryptBase::debug)
    {
        cout << "secret number: " << secretNumber << endl;
    }

    SecByteBlock message(convertHexStrToSecByteBlock(messageIn));
    ECDSA<ECP, SHA256>::PrivateKey privateKey;
    string exp(privKeyIn);
    exp.insert(0, "0x");
    Integer x(exp.c_str());
    privateKey.Initialize(ASN1::secp256r1(), x);
    AutoSeededRandomPool prng;
    if (!privateKey.Validate(prng, 3))
    {
        cout << "unable to verify key" << endl;
        return "failed to verify key";
    }

    ECDSA<ECP, SHA256>::Signer signer(privateKey);
    size_t siglen = signer.MaxSignatureLength();
    string signature(siglen, 0x00);
    siglen = signer.SignMessage(secretNumberGenerator, message.BytePtr(), message.size(),     (byte*)signature.data());
    signature.resize(siglen);

    string encoded;
    HexEncoder encoder;
    encoder.Put((byte *) signature.data(), signature.size());
    encoder.MessageEnd();
    word64 size = encoder.MaxRetrievable();
    if (size)
    {
        encoded.resize(size);
        encoder.Get((byte*)encoded.data(), encoded.size());
    }

    return encoded;
}
燕烨
2023-03-14

DLLTest.exe: Microsoft C异常:CryptoPP::berdecoderer...

您有一个私有指数,但没有私钥。因此您不应该对它调用< code>Load。这导致了Crypto < code > berdecoderer 异常

答案在ECDSA wiki页面上有详细说明,但不是很明显。给定曲线和指数,您需要执行以下操作来初始化privateKey::

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

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

"0x"放在前面可确保Intger类将正确解析ASCII字符串。您还可以将"h"字符附加到字符串。您可以在StringToIntger函数的第2960行周围的Integer.cpp处看到intger类的解析代码。

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

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持有的缓冲区将被整数使用其Decode(BufferedTransform

这是使用HexDecoder的另一种方法(加密有时与脚本语言一样糟糕,:)......

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

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

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

初始化密钥后,应对其进行验证:

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

这将输出二进制数据:

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

如果您想要可打印/可读的东西,请通过Crypto HexEncoder运行它。

 类似资料:
  • 我正在努力从公钥的字符串表示创建ECDSA公钥,即 以前我发现我必须给这个键加上前缀' 04 ',所以不确定这次是否需要这样做? 我正在尝试生成它以用于验证签名 其中要签名的数据是 我现在的粗略代码如下 这是切碎在一起的,所以不能建造。任何帮助都很好 PS我在这里问了一个类似的关于私钥的问题给定曲线和私钥指数的ECDSA私钥的创建?

  • 我也尝试了npm ursa模块,不幸的是没有成功。

  • 我正在尝试用c#签署比特币交易。我有两段代码要完成。我可以使用Bouncy castle创建一组私钥和公钥。我可以将其转换为钱包导入格式ok。 我还可以从ECDSA公钥生成比特币地址。 然而,我想签署一项交易,我所拥有的只是我的私钥。我不想把东西放进钱包里签名。那么,在只提供私钥的情况下,如何生成公钥呢? 我发现了一个javascript方法可以做到这一点: 我在充气城堡看到的唯一方法是生成随机一

  • 我是Openssl的新手,我已经生成了私钥myprivatekey。pem和公钥mypublickey。pem与: 和我的公钥: 接下来我想做的是用通行短语私钥加密我的ecdsa,并对我的公钥进行认证请求,感谢大家的帮助。

  • 我一直在阅读一些RSA文献和堆栈溢出问题,但我没有得到明确的答案。 仅给定一个RSA私钥模和私钥指数,这是我所拥有的全部(也足够用于所有密码相关操作),我能得到相关的公钥模和公钥指数吗? 另外,我是否可以仅用这两个参数获得私钥的编码形式?我在java中尝试了以下方法(java不是实际的请求),但是支持它的OpenSSL引擎失败,错误为:04000090:RSA例程:openSSL_internal

  • 问题内容: 我试图从私钥生成公共ECDSA密钥,但是在Internet上如何进行此操作方面,我还没有找到太多帮助。几乎所有内容都是根据公共密钥规范生成公共密钥的,我不知道该如何获得。到目前为止,这是我汇总的内容: 但是,在运行时,出现以下错误: 我究竟做错了什么?有没有更好/更简便的方法可以做到这一点? 编辑:我设法获得一些代码进行编译,但不能正常工作: 当我运行它时,它会生成一个publicKe