ECDSA 参数在 pem 文件和调试过程之间未对齐

Posted

技术标签:

【中文标题】ECDSA 参数在 pem 文件和调试过程之间未对齐【英文标题】:ECDSA parameters are not aligned between pem file and debug process 【发布时间】:2020-05-23 01:48:03 【问题描述】:

我通过以下命令创建了一个 ECDSA 密钥对

    openssl ecparam -name secp256k1 -out secp256k1.pem openssl ecparam -in secp256k1.pem -genkey -noout -out secp256k1-key.pem openssl ec -in secp256k1-key.pem -pubout -out secp256k1-key-pub.pem

然后我用这个密钥签署一个测试二进制文件

    openssl dgst -sha256 -binary -out sha256_out.bin pmu_msg.bin openssl pkeyutl -sign -in sha256_out.bin -inkey secp256k1-key.pem -out sig_ecdsa.bin -pkeyopt digest:sha256 openssl pkeyutl -verify -in sha256_out.bin -sigfile sig_ecdsa.bin -pkeyopt digest:sha256 -pubin -inkey secp256k1-key-pub.pem

在这一步之前一切都很好。 然后我用widbg调试step.6命令来了解整个验证流程。 我首先从 pem 文件中转储 EC 参数。 当我检查windbg中的一些变量时;我感到困惑,因为价值不符合我的预期。 E:\project\ecdsa\secp256k1>openssl ecparam -in secp256k1.pem -text -param_enc 显式 -noout

字段类型:prime-field

素数:

00:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:fe:ff: ff:fc:2f

答:0

B: 7 (0x7)

生成器(未压缩):

04:79:be:66:7e:f9:dc:bb:ac:55:a0:62:95:ce:87: 0b:07:02:9b:fc:db:2d:ce:28:d9:59:f2:81:5b:16: f8:17:98:48:3a:da:77:26:a3:c4:65:5d:a4:fb:fc: 0e:11:08:a8:fd:17:b4:48:a6:85:54:19:9c:47:d0: 8f:fb:10:d4:b8

顺序: 00:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff: ff:fe:ba:ae:dc:e6:af:48:a0:3b:bf:d2:5e:8c:d0: 36:41:41

辅因子:1 (0x1)

E:\project\ecdsa\secp256k1>openssl ec -in secp256k1-key.pem -text -noout

私钥:(256 位)

隐私:

8e:73:0d:3f:1b:91:84:46:08:37:e1:57:76:6f:3a: 0d:45:13:b0:47:e1:8a:4a:10:c0:e5:5e:00:2f:3b: fd:98

酒吧:

04:90:66:38:2f:91:f9:08:32:36:fd:dd:21:8f:91: ce:84:a8:94:54:a1:bd:10:48:05:20:40:7b:6d:77: 53:25:6f:39:b7:3c:30:0f:e4:9b:a0:40:ee:48:bf: 09:22:18:70:f4:cd:9b:b0:9d:7d:9c:d8:99:65:b6: 87:71:ef:ec:6c

ASN1 OID:secp256k1

从上面的输出,我假设

生成点 X 是

79:be:66:7e:f9:dc:bb:ac:55:a0:62:95:ce:87:0b:07: 02:9b:fc:db:2d:ce:28:d9:59:f2:81:5b:16:f8:17:98:

生成点 Y 是

48:3a:da:77:26:a3:c4:65:5d:a4:fb:fc:0e:11:08:a8: fd:17:b4:48:a6:85:54:19:9c:47:d0:8f:fb:10:d4:b8

对于公钥,假设 Qa = (da X Generator Point) Qa点X是

90:66:38:2f:91:f9:08:32:36:fd:dd:21:8f:91:ce:84: a8:94:54:a1:bd:10:48:05:20:40:7b:6d:77:53:25:6f:

Qa 点 Y 是

39:b7:3c:30:0f:e4:9b:a0:40:ee:48:bf:09:22:18:70: f4:cd:9b:b0:9d:7d:9c:d8:99:65:b6:87:71:ef:ec:6c

然后在 openssl!ossl_ecdsa_verify_sig+0x40a [E:\project\openssl\openssl_v\openssl\crypto\ec\ecdsa_ossl.c @ 435]

我从 eckey 结构中转储公钥 X/Y

0:000:x86> ?? eckey->pub_key->X->d

无符号整数 * 0x006b17e0

0:000:x86> 数据库 0x006b17e0

006b17e0 d5 7e 76 7a b0 6e d0 1d-fe 56 63 ab 47 45 27 1b .~vz.n...Vc.GE'。

006b17f0 e9 7c 09 94 99 bb 6a 6e-c5 24 66 4e 是 75 15 a8 .|..jn.$fN.u..

006b1800 fd fd fd fd ab ab ab ab ab ab ab ee ee ee fe ....

0:000:x86> ?? eckey->pub_key->Y->d

无符号整数 * 0x006b1840

0:000:x86> 数据库 0x006b1840

006b1840 f8 42 f5 18 3e c5 d4 18-29 4d c9 a5 e1 c9 2c e2 .B..>...)M....,.

006b1850 c6 e2 ec cf 82 b9 85 d6-56 37 64 e8 0c 4f 31 54 ........V7d..O1T

006b1860 fd fd fd fd ab ab ab-ab ab ab ab ee ee ee fe ....

来自windbbg, 公钥,点 X =

d5 7e 76 7a b0 6e d0 1d-fe 56 63 ab 47 45 27 1b e9 7c 09 94 99 bb 6a 6e-c5 24 66 4e 是 75 15 a8

但在 pem 文件中,点 x 是

90:66:38:2f:91:f9:08:32:36:fd:dd:21:8f:91:ce:84: a8:94:54:a1:bd:10:48:05:20:40:7b:6d:77:53:25:6f:

公钥,点 Y =

f8 42 f5 18 3e c5 d4 18-29 4d c9 a5 e1 c9 2c e2 c6 e2 ec cf 82 b9 85 d6-56 37 64 e8 0c 4f 31 54

但是在pem文件中,Y点是

39:b7:3c:30:0f:e4:9b:a0:40:ee:48:bf:09:22:18:70: f4:cd:9b:b0:9d:7d:9c:d8:99:65:b6:87:71:ef:ec:6c

这些值与我在公共 pem 文件中看到的不同。

然后我将生成器点转储到 windbg 并有同样的疑问。

0:000:x86> ?? eckey->group->generator->X->d unsigned int * 0x006b13c0

0:000:x86> 数据库 0x006b13c0

006b13c0 97 20 7e 48 5a 2e 36 d7-db 66 bc 29 53 29 1e 23 。 ~HZ.6..f.)S).#

006b13d0 9c 12 fd 33 c0 48 9f 97-48 9f 08 e9 43 e6 81 99 ...3.H..H...C...

006b13e0 fd fd fd fd ab ab ab-ab ab ab ab ee fe ee fe ....

0:000:x86> ?? eckey->group->generator->Y->d unsigned int * 0x006b1420

0:000:x86> 数据库 0x006b1420

006b1420 e2 ab db d3 d2 a6 5e b1-4d c6 1d 1f 5d 5d fc 8d ......^.M...]]..

006b1430 36 c1 19 ac 9a b5 b6 70-d6 82 a5 d4 1f 85 3f cf 6......p......?.

006b1440 fd fd fd fd ab ab ab-ab ab ab ab ee fe ee fe ....

谁能给我一些cmets?

谢谢

【问题讨论】:

如果您对计算机输入和输出使用“代码”格式(并且没有额外的行),这将更容易阅读。您应该将它用于示例命令,尽管在那里不太需要。在编辑器中单击带圆圈的问号,然后单击“代码”选项卡进行说明。 【参考方案1】:

OpenSSL 在 Montgomery form 内部维护椭圆曲线点的坐标,以实现更高效的计算 - 并且还使用投影而不是仿射坐标,尽管此时这并不重要,因为尚未完成真正的计算Z 只是编码(1)。请参阅ec_GFp_simple_set_Jprojective_coordinates_GFp in ecp_smpl.c 并注意解析为ec_GFp_mont_field_encode in ecp_mont.cgroup->meth->field_encode 步骤,该步骤使用宏BN_to_montgomery 扩展为调用BN_mod_mul_montgomery in bn_mont.c

OpenSSL 代码是为了提高效率而不是为了便于阅读而编写的。而作为 C 会增加更多的混乱。另外,其中大部分仍然遵循 EAY 设定的简洁名称的传统,几乎没有 cmets。如果你想从调试中学习——尽管坦率地说,我怀疑你会比从规范中得到的更多,可能更少,因为 ECC 的有趣部分在于数学而不是代码——我建议使用 Java 或 C#与 BouncyCastle。

【讨论】:

谢谢戴夫。因为我们有硬件引擎来加速模乘、模加等;有助于减少 SW 的计算工作量。我想生成签名并按照andrea.corbellini.name/2015/05/30/… 使用硬件引擎验证签名。给定r。 s 和 hash 以及 .pem 文件中的所有参数。我假设中间输出值应该与 openssl EC 结构中保存的变量相同。但是由于openssl使用的是投影坐标而不是仿射坐标;我们不能使用 openssl 作为参考模型。

以上是关于ECDSA 参数在 pem 文件和调试过程之间未对齐的主要内容,如果未能解决你的问题,请参考以下文章

如何将 ECDSA 密钥转换为 PEM 格式

如何在 NodeJS 中生成 ECDSA 签名而不需要 PEM 密钥格式?

Openssl ECDSA:私钥密码

如何在 C# 中加载私有 ecdsa 密钥 es256?

如何在 open-ssh 和 dropbear 之间匹配 ECDSA 指纹

如何使用使用 sha1ecdsa 的公钥验证数据是不是符合签名?