2013-05-15 43 views
2

如何在Crypto ++中生成壓縮的ECDSA密鑰?Crypto ++和Compressed EC keys

AutoSeededRandomPool prng; 
ECDSA<ECP, SHA1>::PrivateKey privateKey; 
ECDSA<ECP, SHA1>::PublicKey publicKey; 
privateKey.Initialize(prng, CryptoPP::ASN1::secp256r1()); 

const Integer& x1 = privateKey.GetPrivateExponent(); 
cout << "priv: " << std::hex << x1 << endl; 
privateKey.MakePublicKey(publicKey); 
const ECP::Point& q = publicKey.GetPublicElement(); 
const Integer& qx = q.x; 
const Integer& qy = q.y; 
cout << "pub x: " << std::hex << qx << endl; 
cout << "pub y: " << std::hex << qy << endl; 

此代碼生成密鑰對並打印公鑰的X和Y組件。

我需要知道,如果有打印壓縮關鍵的Y分量的方式,或者如果我需要從非壓縮y分量生成它。如果我需要生成它,有人可以鏈接我如何使用Integer類的一個很好的解釋嗎?

回答

4

在CryptoPP怎樣才能壓縮ECDSA密鑰?

不創建一個壓縮的關鍵。你生成一個公鑰,然後你壓縮它,如果這是需要的。從How to construct a public ECDSA key with point compression turned on?在Crpyto ++用戶組:

ECDSA<ECP, SHA1>::Verifier verifier(...); 
verifier.AccessKey().AccessGroupParameters().SetPointCompression(true); 

你的情況,這將是:

publicKey.AccessGroupParameters().SetPointCompression(true); 

因爲verifier.AccessKey()返回ECDSA公共密鑰。


我需要知道,如果有打印壓縮關鍵

壓縮的Y分量的呈現格式的選項或優化的方式。您不能在壓縮的序列化密鑰上打印Y組件,因爲它不存在(請參見下面的ASN.1轉儲)。

隨着對時,Y「的簡寫」壓縮將是1或-1,取決於分量的符號(符號表示什麼象限點是在)。這個想法是有人給你發送{1,X}對或{-1,X}對,你可以爲Y解決,因爲你知道它應該在哪個象限。如果Y只允許爲正,你只需要序列化{X}(而不是{-1,X}或{1,X})。 (我沒有深入研究書籍或標準,所以在這裏可能會出現一些錯誤)。


...或者,如果我需要從非壓縮y分量生成它。如果我需要生成它,有人可以鏈接我如何使用Integer類的一個很好的解釋嗎?

我不知道你是在談論在這裏。點壓縮影響演示文稿。如果你打開點壓縮並獲取Y,你仍然會得到Y.您無法在壓縮點上進行計算。你需要X和Y座標。


以下內容添加到您的程序:

publicKey.AccessGroupParameters().SetPointCompression(false); 
ByteQueue q1; 
publicKey.Save(q1); 
cout << "Uncompressed size: " << dec << q1.MaxRetrievable() << endl; 

publicKey.AccessGroupParameters().SetPointCompression(true); 
ByteQueue q2; 
publicKey.Save(q2); 
cout << "Compressed size: " << dec << q2.MaxRetrievable() << endl; 

這裏是我得到的輸出:

$ ./cryptopp-test.exe 
priv: 4ce30d22d9593d9c7f4406eda1ce0740c7486106374d0abe7e352e1d5b1d5622h 
pub x: 41a9bc936b6d1dd3a1ded997d7da08f1df990e9b50f9b58e9e4fd9319758ea34h 
pub y: 4ad39ffb79c402063a99ecbc0cac8fde606db6764ace90933feee5f8d65937a2h 
Uncompressed size: 311 
Compressed size: 246 

如果你打開點壓縮後提取Y,你仍然會得到4ad39ffb79c402063a99ecbc0cac8fde606db6764ace90933feee5f8d65937a2h,因爲壓縮會影響演示。


現在,添加以下轉儲未壓縮和壓縮的鍵:

FileSink fs1("key-1.der", true); 
q1.TransferTo(fs1); 

FileSink fs2("key-2.der", true); 
q2.TransferTo(fs2); 

的鍵在ASN.1的DER編碼傾倒並符合Certicom的的SEC 1: Elliptic Curve Cryptography(和在較小程度上,ANSI 9.62RFC 5480, ECC SubjectPublicKeyInfo Format - 請參見下面的Field Element的OCTET STRING vs BIT STRING)。

你可以在上面運行彼得古特曼的dumpasn1

$ dumpasn1.exe key-1.der 
    0 307: SEQUENCE { 
    4 236: SEQUENCE { 
    7 7:  OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) 
16 224:  SEQUENCE { 
19 1:  INTEGER 1 
22 44:  SEQUENCE { 
24 7:   OBJECT IDENTIFIER prime-field (1 2 840 10045 1 1) 
33 33:   INTEGER 
     :   00 FF FF FF FF 00 00 00 01 00 00 00 00 00 00 00 
     :   00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF 
     :   FF 
     :   } 
68 68:  SEQUENCE { 
70 32:   OCTET STRING 
     :   FF FF FF FF 00 00 00 01 00 00 00 00 00 00 00 00 
     :   00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FC 
104 32:   OCTET STRING 
     :   5A C6 35 D8 AA 3A 93 E7 B3 EB BD 55 76 98 86 BC 
     :   65 1D 06 B0 CC 53 B0 F6 3B CE 3C 3E 27 D2 60 4B 
     :   } 
138 65:  OCTET STRING 
     :   04 6B 17 D1 F2 E1 2C 42 47 F8 BC E6 E5 63 A4 40 
     :   F2 77 03 7D 81 2D EB 33 A0 F4 A1 39 45 D8 98 C2 
     :   96 4F E3 42 E2 FE 1A 7F 9B 8E E7 EB 4A 7C 0F 9E 
     :   16 2B CE 33 57 6B 31 5E CE CB B6 40 68 37 BF 51 
     :   F5 
205 33:  INTEGER 
     :   00 FF FF FF FF 00 00 00 00 FF FF FF FF FF FF FF 
     :   FF BC E6 FA AD A7 17 9E 84 F3 B9 CA C2 FC 63 25 
     :   51 
240 1:  INTEGER 1 
     :  } 
     :  } 
243 66: BIT STRING 
     :  04 41 A9 BC 93 6B 6D 1D D3 A1 DE D9 97 D7 DA 08 
     :  F1 DF 99 0E 9B 50 F9 B5 8E 9E 4F D9 31 97 58 EA 
     :  34 4A D3 9F FB 79 C4 02 06 3A 99 EC BC 0C AC 8F 
     :  DE 60 6D B6 76 4A CE 90 93 3F EE E5 F8 D6 59 37 
     :  A2 
     : } 

$ dumpasn1.exe key-2.der 
    0 243: SEQUENCE { 
    3 204: SEQUENCE { 
    6 7:  OBJECT IDENTIFIER ecPublicKey (1 2 840 10045 2 1) 
15 192:  SEQUENCE { 
18 1:  INTEGER 1 
21 44:  SEQUENCE { 
23 7:   OBJECT IDENTIFIER prime-field (1 2 840 10045 1 1) 
32 33:   INTEGER 
     :   00 FF FF FF FF 00 00 00 01 00 00 00 00 00 00 00 
     :   00 00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF 
     :   FF 
     :   } 
67 68:  SEQUENCE { 
69 32:   OCTET STRING 
     :   FF FF FF FF 00 00 00 01 00 00 00 00 00 00 00 00 
     :   00 00 00 00 FF FF FF FF FF FF FF FF FF FF FF FC 
103 32:   OCTET STRING 
     :   5A C6 35 D8 AA 3A 93 E7 B3 EB BD 55 76 98 86 BC 
     :   65 1D 06 B0 CC 53 B0 F6 3B CE 3C 3E 27 D2 60 4B 
     :   } 
137 33:  OCTET STRING 
     :   03 6B 17 D1 F2 E1 2C 42 47 F8 BC E6 E5 63 A4 40 
     :   F2 77 03 7D 81 2D EB 33 A0 F4 A1 39 45 D8 98 C2 
     :   96 
172 33:  INTEGER 
     :   00 FF FF FF FF 00 00 00 00 FF FF FF FF FF FF FF 
     :   FF BC E6 FA AD A7 17 9E 84 F3 B9 CA C2 FC 63 25 
     :   51 
207 1:  INTEGER 1 
     :  } 
     :  } 
210 34: BIT STRING 
     :  02 41 A9 BC 93 6B 6D 1D D3 A1 DE D9 97 D7 DA 08 
     :  F1 DF 99 0E 9B 50 F9 B5 8E 9E 4F D9 31 97 58 EA 
     :  34 
     : } 

注意區別:

# key-1.der 
243 66: BIT STRING 
     :  04 41 A9 BC 93 6B 6D 1D D3 A1 DE D9 97 D7 DA 08 
     :  F1 DF 99 0E 9B 50 F9 B5 8E 9E 4F D9 31 97 58 EA 
     :  34 4A D3 9F FB 79 C4 02 06 3A 99 EC BC 0C AC 8F 
     :  DE 60 6D B6 76 4A CE 90 93 3F EE E5 F8 D6 59 37 
     :  A2 

與:

# key-2.der 
210 34: BIT STRING 
     :  02 41 A9 BC 93 6B 6D 1D D3 A1 DE D9 97 D7 DA 08 
     :  F1 DF 99 0E 9B 50 F9 B5 8E 9E 4F D9 31 97 58 EA 
     :  34 
     : } 

前有編碼的兩個整數,而第二有一個Integer編碼。常見值爲41 A9 BC 93 ... 97 58 EA 34,這就是您的pub x以上。從關鍵字2丟失的字符串是4A D3 9F FB ... D6 59 37 A2,這就是上面的pub y。爲了完整性,這些值被編碼爲{X,Y}或{X},而不是ASN.1的整數編碼。

最後的區別是第一個 BIT STRING:02與04(或03)的八位字節。 04表示它是一個未壓縮的點。從RFC 5480,第2.2節:

The first octet of the OCTET STRING indicates whether the key is 
    compressed or uncompressed. The uncompressed form is indicated 
    by 0x04 and the compressed form is indicated by either 0x02 or 
    0x03 (see 2.3.3 in [SEC1]). The public key MUST be rejected if 
    any other value is included in the first octet. 

而綜觀目前的標準和第2.2節之後,加密++可能有一個錯誤:它寫BIT STRING,但該標準顯然是討論一個OCTET STRING

編輯1:看起來這也是ANSI 9.62下的Crypto ++ bug。第6.2節,語法有限域元素和橢圓曲線點(第20)

A finite field element shall be represented by a value of type FieldElement: 
     FieldElement ::= OCTET STRING 
    The value of FieldElement shall be the octet string representation of a field 
    elementfollowing the conversion routine in Section 4.3.1. 
    An elliptic curve point shall be represented by a value of type ECPoint: 
     ECPoint ::= OCTET STRING 

編輯2:加密++是使用由稱爲Certicom的SEC 1: Elliptic Curve Cryptography指定的格式。附錄C(第77頁)指出:

Finally, a specific field element is represented by the following type 
     FieldElement ::= OCTET STRING 
    whose value is the octet string obtained from the conversion routines 
    given in Section 2.3.5.