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

创建ECDSA公钥给定曲线和公共点?

林浩漫
2023-03-14

我正在努力从公钥的字符串表示创建ECDSA公钥,即

string     devicePublicKey("86FB5EB3CA0507226BE7197058B9EC041D3A3758D9D9C91902ACA3391F4E58AEF13AFF63CC4EF68942B9B94904DC1B890EDBEABD16B992110624968E894E560E");

以前我发现我必须给这个键加上前缀' 04 ',所以不确定这次是否需要这样做?

我正在尝试生成它以用于验证签名

string ecs04b2ExpSignature("0199E984CEC75DDCA7F1DDF6E53E2E67352A2BE38A4B66F8ED596606FAB983FF300CAA76DE88CED9D563A5C03E8F3A7C000780F3F2061C611E9AA0B18B460D77");

其中要签名的数据是

string      ecs04b2SigningData("020000000000000001FFFFFFFFFFFFFFFE123456789ABCDEF000B3DA2000000100000300000003030003000300");

我现在的粗略代码如下

SecByteBlock message(convertHexStrToSecByteBlock(messageIn));
SecByteBlock signature(convertHexStrToSecByteBlock(signatureIn));

ECDSA<ECP, SHA256>::PublicKey publicKey;
string inPublicKey("04");
inPublicKey.append(pubKeyIn);
SecByteBlock pubKey = encryptBase::convertHexStrToSecByteBlock(inPublicKey);



ECP::Point p;
publicKey.AccessGroupParameters().Initialize(CryptoPP::ASN1::secp256r1());
publicKey.GetGroupParameters().GetCurve().DecodePoint(p, pubKey, publicKey.GetGroupParameters().GetCurve().EncodedPointSize(true));
publicKey.SetPublicElement(p);

//ByteQueue qt;
//qt.Put((byte*)exp.c_str(),(size_t)exp.size());
AutoSeededRandomPool prng;
bool result = publicKey.Validate(prng, 3);
if (result) 
{  
    // Load public key (in ByteQueue, X509 format)
    ECDSA<ECP, SHA256>::Verifier verifier(publicKey);

    bool result = verifier.VerifyMessage(message.data(), messageIn.size(), signature.data(), signature.size());
    if (result)
        cout << "Verified signature on message" << endl;
    else
        cerr << "Failed to verify signature on message" << endl;
}
else
{
    cout << "Failed to validate key" << endl;
}

这是切碎在一起的,所以不能建造。任何帮助都很好

PS我在这里问了一个类似的关于私钥的问题给定曲线和私钥指数的ECDSA私钥的创建?

共有2个答案

郑锦
2023-03-14

这是您关于如何使用VerifyMessage的第二个问题的答案:

...
publicKey.Initialize(ASN1::secp256r1(), q);

string msg = "020000000000000001FFFFFFFFFFFFFFFE123456789ABCDEF000B3DA2000000100000300000003030003000300";
string sig = "0199E984CEC75DDCA7F1DDF6E53E2E67352A2BE38A4B66F8ED596606FAB983FF300CAA76DE88CED9D563A5C03E8F3A7C000780F3F2061C611E9AA0B18B460D77";

string mm, ss;

decoder.Detach(new StringSink(mm));
decoder.Put((byte*)msg.data(), msg.size());
decoder.MessageEnd();

decoder.Detach(new StringSink(ss));
decoder.Put((byte*)sig.data(), sig.size());
decoder.MessageEnd();

ECDSA<ECP, SHA256>::Verifier verifier(publicKey);
result = verifier.VerifyMessage((byte*)mm.data(), mm.size(), (byte*)ss.data(), ss.size());

if( result )
{
    cout << "Verified message" << endl;
}
else
{ 
    cerr << "Failed to verify message" << endl;
    exit(1);
}

HexDecoder上调用Detach,删除当前筛选器,并用新筛选器替换它。在上面的代码中,它是<code>StringSink</code>。您必须这样做以确保内存不会泄漏。

您的消息未在公钥下验证:

$ ./cryptopp-test.exe
Validated public key
Failed to verify message

您还可以尝试验证ASCII消息而不是二进制消息,但它也无法验证:

decoder.Attach(new StringSink(mm));
decoder.Put((byte*)msg.data(), msg.size());
decoder.MessageEnd();

// Swap in the ASCII message for the binary message
mm = msg;

所以有人给了你错误的消息,错误的签名或错误的公钥(或某种组合)。

海雪松
2023-03-14

答案在ECDSA维基页面上有详细说明,但它并不明显。您需要执行以下操作来初始化给定曲线和公共点的公钥:

string pt = "2DB45A3F21889438B42C8F464C75292BACF5FDDB5DA0B492501B299CBFE92D8F"
            "DB90FC8FF4026129838B1BCAD1402CAE47FE7D8084E409A41AFCE16D63579C5F";

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

ECP::Point q;
size_t len = decoder.MaxRetrievable();
// len should be GetField().MaxElementByteLength()

q.identity = false;
q.x.Decode(decoder, len/2);
q.y.Decode(decoder, len/2);

ECDSA<ECP, SHA256>::PublicKey publicKey;
publicKey.Initialize(ASN1::secp256r1(), q);

bool result = publicKey.Validate( prng, 3 );
if( result )
{
    cout << "Validated public key" << endl;
}
else
{
    cerr << "Failed to validate public key" << endl;
    exit(1);
}

const ECP::Point& qq = publicKey.GetPublicElement();
cout << "Q.x: " << std::hex << qq.x << endl;
cout << "Q.y: " << std::hex << qq.y << endl;

上述程序产生以下结果。

$ ./cryptopp-test.exe
Validated public key
Q.x: 2db45a3f21889438b42c8f464c75292bacf5fddb5da0b492501b299cbfe92d8fh
Q.y: db90fc8ff4026129838b1bcad1402cae47fe7d8084e409a41afce16d63579c5fh

不能使用<code>GetField()。MaxElementByteLength(),因为唯一可用的是xy坐标。在初始化底层的<code>DL_GroupParameters_EC之前,字段大小之类的内容将不可用

例如,以下情况会导致分段错误:

ECDSA<ECP, SHA256>::PublicKey publicKey;
unsigned int u = publicKey.GetGroupParameters().GetCurve().GetField().MaxElementByteLength();
cout << "Field element length: " << u << endl;

您可以通过以下方式篡改公钥以确保验证失败:

q.y.Decode(decoder, len/2);
q.y++;
 类似资料:
  • 我是新到cryptopp,并一直在努力为ECDSA签名创建私钥。 我有一个十六进制编码的私有指数。这存储为字符串。 我想用它来使用ECDSA签署文本块。我的代码看起来有点像这样 此代码在 Visual Studio 中生成以下错误,当我尝试执行 privateKey.load(...) 我猜我正在做一些有点愚蠢的事情...任何帮助都会很棒??? PS我在GMAC一代中使用ECDH时遇到了类似的问题

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

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

  • 我试图从私钥中生成一个公共ECDSA密钥,但我还没有在互联网上找到多少关于如何实现这一点的帮助。几乎所有的事情都是为了从公钥规范生成公钥,我不知道如何得到它。到目前为止,我总结了以下内容: 但是,在运行时,我会出现以下错误: 我做错了什么?有更好/更简单的方法吗? 编辑:我已经设法编译了一些代码,但它不能正常工作: 当我运行它时,它会生成一个公钥,但它不是私钥对应的公钥。

  • 问题内容: 我正在做publicKey.getEncoded(),然后在前面附加“ ssh- rsa”,然后对它进行base64编码。然后添加SSH2标头/页脚。但是不会解码… 问题答案: Java公共密钥被编码为标准的X.509 SubjectPublicKeyInfo结构。 SSH2使用其自己的简单格式。Base-64对下面显示的方法的结果进行编码,并附加必要的SSH2标头和页脚。 有关将其他

  • 我正在处理一些ECC加密问题。 目标是用C或bash编写程序,它将以由128个十六进制字符组成的散列作为输入(例如:8A9A35145C4EA5260DF9972C804FE2D3F9F3D7A2AC01A6BEB21C82BB30957B3952273AC9166B90C120737A925780F84A1D2359E7AA05201C674D29746FCA07),并将从