2014-12-05 35 views
2

我与创作从公钥的字符串表示ECDSA公共密钥的挣扎即创建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我问有关私钥这里Creation of ECDSA private key given curve and private exponent?

回答

1

答案是详细的ECDSA wiki page过类似的问题,但它不是显而易见的。您需要执行以下步骤来初始化给出的曲线和公共点publicKey

string pt = "2DB45A3F21889438B42C8F464C75292BACF5FDDB5DA0B492501B299CBFE92D8F" 
      "DB90FC8FF4026129838B1BCAD1402CAE47FE7D8084E409A41AFCE16D63579C5F"; 

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

ECP::Point q; 
size_t len = decoder.MaxRetrievable(); 
assert(len == SHA256::DIGESTSIZE * 2); 

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 

测试:

assert(len == SHA256::DIGESTSIZE * 2); 

是怎样的一个杂牌的。这是您要使用的,而不是SHA256::DIGESTSIZE值:

GetField().MaxElementByteLength() 

但你不能使用它,因为唯一可用的东西是xy坐标。在使用公钥初始化底层DL_GroupParameters_EC<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++; 
+0

这个作品完美!非常感谢您的帮助。我与cryptoPP wiki维基共同努力,因为似乎有一些内容出版。我使用的是http://www.cryptopp.com/wiki/Elliptic_Curve_Digital_Signature_Algorithm请注意我在上面的例子中更新了公钥(我的错误) – gizmo 2014-12-08 11:48:52

0

这里的答案关于如何使用的第二个问题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删除当前过滤器,并用新过滤器替换它。在上面的代码中,它的StringSink。你必须这样做,以确保内存不泄漏。

你的消息不公钥下验证:

$ ./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; 

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

+0

这个工作完美。我已在上面的示例中更新了密钥,并且验证消息正常。再次感谢你的帮助 – gizmo 2014-12-08 11:51:18