2014-12-05 34 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