加密++和压缩EC密钥
Crypto++ and Compressed EC keys
如何在Crypto++中生成压缩的ECDSA密钥?
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类的很好的解释吗?
如何在CryptoPP中生成压缩的ECDSA密钥?
没有创建压缩密钥。你生成一个公钥,然后压缩它,如果这是必要的。从如何构建一个公开的ECDSA密钥与点压缩打开?在crypto ++用户组中:
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编码转储,并符合certiccom的SEC 1:椭圆曲线加密(以及在较小程度上,ANSI 9.62和RFC 5480, ECC SubjectPublicKeyInfo格式-参见下面的字段元素的OCTET STRING
vs BIT STRING
)。
你可以运行Peter Gutmann的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,而第二个有一个编码的Integer。常见的值是41 A9 BC 93 ... 97 58 EA 34
,这就是上面的pub x
。key-2中缺失的字符串是4A D3 9F FB ... D6 59 37 A2
,也就是上面的pub y
。为了完整起见,这些值被编码为{X,Y}或{X},而不是ASN.1的整数编码。
最后的区别是BIT STRING的第一个位元组:02和04(或03)。04表示未压缩点。来自RFC 5480, Section 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节之后,Crypto++可能有一个bug:它写的是BIT STRING
,但标准显然讨论的是OCTET STRING
。
EDIT 1:这似乎也是ANSI 9.62下的Crypto++错误。第6.2节,有限域单元和椭圆曲线点的语法(p. 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
EDIT 2: Crypto++使用certiccom的SEC 1:椭圆曲线加密指定的格式。附录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.
- SSH通过/sbin/SSH无法读取RSA密钥文件(从控制台运行)
- 允许从 std::map 的密钥窃取资源?
- TMap::Emplace() 在应用现有密钥时会覆盖吗?
- 在没有密钥的情况下读取密文的剩余噪声预算
- 如何修复无效的API密钥,IP或操作权限错误?
- 所有可能的链接生成器与64位密钥
- 如何在unordered_map中更改密钥?
- 获取当前密钥状态?
- curl_easy_perform() 失败:SSL 对等证书或 SSH 远程密钥不正常
- 将密钥发送到非前台的游戏窗口
- 有哪些方法可以对基于 256 位密钥的矩阵进行加扰?
- 如何在精灵表上的两个不同部分之间来回切换,同时用户仍使用 SFML 持有密钥
- 如何将CNG密钥转换为OpenSSL EVP_PKEY(反之亦然)?
- 运行密钥密码解密知道密钥?
- std::unordered_map 运算符 [] 是否对非现有密钥进行零初始化?
- 封装 std::map 以允许迭代,但没有直接密钥访问?
- 如果我使用同一个密钥推送用户数据两次,会发生什么
- 如何在C++中创建自己的编译密钥
- OpenSSL:读取EC密钥,然后再次写入,这是不同的
- 加密++和压缩EC密钥