Closed yebin-yu closed 5 months ago
最终得到的python脚本为:
res = base64.b64encode(bytes.fromhex("00000003736d3200000003736d3200000041" + "04" +
'de7e78a3e1c40b1d9a9c08c3b17c13e24e59b72385dde24a1f0e899b216554f9' +
'632c1e985729b75fbc05aa2809c418cb2ef51bb7bc6a22ec3f155291cecb8f83'))
结果为:
AAAAA3NtMgAAAANzbTIAAABBBN5+eKPhxAsdmpwIw7F8E+JOWbcjhd3iSh8OiZshZVT5YywemFcpt1+8BaooCcQYyy71G7e8aiLsPxVSkc7Lj4M=
可以看到,和使用ssh-keygen生成的秘钥大小一致,且前面部分都一样
sm2 AAAAA3NtMgAAAANzbTIAAABBBDFm8NOcCa/yaI7pVJuGpqbUuToMLREOl5+WhWYRV8FD/DDtRFPMiIdvWWHEG+71ZRc4Hagx93B3H05X/thNiOE= root@yebinyu
前面的AAAAA3NtMgAAAANzbTIAAABBB
,即00000003736d3200000003736d3200000041
,解释如下
AAAA: 固定前缀,表示密钥类型为SM2。
3: 一个字节,表示SM2公钥版本号为3。
NtMgAAAANzbTIAAABBB: 固定字符串,用于标识SM2公钥。
完成将公钥转成openssh需要的sshkey结构体。 用ssh-keygen生成的公钥测试:测试通过
得到的公钥为:
AAAAA3NtMgAAAANzbTIAAABBBAAKN4ft4dvE4cOJya4hN8sSO3WU5K4t2Fm4nh/5VGUhAJgeLGNftylXKKpbzLGMSbcb9S7sImq8kVIVP4OPy84=
直接在OPENSSL的函数中解析失败,怀疑是公钥格式问题,从demo中打印的x和y来看,长度不够需要补0
发现问题,转换失败
Breakpoint 2, sshkey_ec_validate_public (group=0x5b3225f48950, public=public@entry=0x5b3225f49030) at sshkey.c:2601
2601 {
(gdb)
2618 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
(gdb)
2623 if (EC_POINT_is_at_infinity(group, public))
(gdb)
2626 if ((x = BN_new()) == NULL ||
(gdb)
2635 if (EC_GROUP_get_order(group, order, NULL) != 1 ||
(gdb)
2641 if (BN_num_bits(x) <= BN_num_bits(order) / 2 ||
(gdb)
2646 if ((nq = EC_POINT_new(group)) == NULL) {
(gdb)
2650 if (EC_POINT_mul(group, nq, NULL, public, order, NULL) != 1) {
(gdb)
2654 if (EC_POINT_is_at_infinity(group, nq) != 1)
(gdb)
2666 BN_clear_free(x);
(gdb)
2667 BN_clear_free(y);
(gdb)
2668 BN_clear_free(order);
(gdb)
2669 BN_clear_free(tmp);
(gdb) print ret
$1 = -20
(gdb)
代码在sshkey.c,显示该坐标点不是一个无穷点
int
sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
{
// ......
if (EC_POINT_is_at_infinity(group, nq) != 1)
goto out;
// ......
查看openssl的源码,发现要求的数据默认是大端序,猜测可能是大小端序问题,测试一下
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
{
return bin2bn(s, len, ret, BIG, UNSIGNED);
}
所以将公钥转换大小序,python代码如下
def swap_endian(hex_str):
if not isinstance(hex_str, str) or not all(x in "0123456789abcdefABCDEF" for x in hex_str):
raise TypeError("输入数据必须为有效的 16 进制字符串")
data = bytearray.fromhex(hex_str)
data.reverse()
return data.hex()
res = base64.b64encode(bytes.fromhex("00000003736d3200000003736d3200000041" + "04" +
swap_endian('de7e78a3e1c40b1d9a9c08c3b17c13e24e59b72385dde24a1f0e899b216554f9') +
swap_endian('632c1e985729b75fbc05aa2809c418cb2ef51bb7bc6a22ec3f155291cecb8f83')))
结果为:
AAAAA3NtMgAAAANzbTIAAABBBPlUZSGbiQ4fSuLdhSO3WU7iE3yxwwicmh0LxOGjeH7eg4/LzpFSFT/sImq8txv1LssYxAkoqgW8X7cpV5geLGM=
还是失败
获取sm2公钥的坐标点,即x和y
获取过程1 - demo获取
UKEY - PubKey
print code
打印如下
获取过程2 - gdb获取
获取内容
获取公钥的函数,其中buf指向RSA公钥结构(RSAPUBLICKEYBLOB)或者ECC公钥结构(ECCPUBLICKEYBLOB),如果此参数为NULL时,由pulBlobLen返回pbBlob的长度
代码中实际用到的是
ECCPUBLICKEYBLOB
对buf的内容进行打印