最近要生成SM2签名验签测试数据,使用了Python的gmssl库,里面包含了SM2加解密、签名验签的函数,但是要从别的地方生成公私钥对比较麻烦,因此通过SM2内部实现的私有函数实现公私钥对的生成,密钥对生成规则如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| from gmssl import sm2, func
class Generator_SM2_Key(sm2.CryptSM2): def __init__(self, private_key = None, public_key = None, ecc_table = sm2.default_ecc_table, mode = 0): super().__init__(private_key, public_key, ecc_table, mode) def get_private_key(self): if self.private_key is None: self.private_key = func.random_hex(self.para_len) return self.private_key def get_public_key(self): if self.public_key is None: self.public_key = self._kg(int(self.get_private_key(), 16), self.ecc_table['g']) return self.public_key
sm2key = Generator_SM2_Key() private_key = sm2key.get_private_key() public_key = sm2key.get_public_key() print('private_key:',private_key) print('public_key: ',public_key)
sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key)
data = bytes.fromhex('91cacfd230122fc832fc1b0b2aa07d93') enc_data = sm2_crypt.encrypt(data) dec_data =sm2_crypt.decrypt(enc_data) assert dec_data == data print('Enc: ',enc_data.hex())
random_hex_str = func.random_hex(sm2_crypt.para_len) sign = sm2_crypt.sign_with_sm3(data, random_hex_str) assert sm2_crypt.verify_with_sm3(sign, data) print('Sign:',sign)
|
输出如下:
1 2 3 4
| private_key: df67f088cc94143a51c060acb4357cfc86ad14492476caf418480385de72439 public_key: ce343dae8cd86d3342cab71b1e33375332a89d01cc2565b207e8bedd2a33e17779e36b052217de31fb8a8230fbfd06e93c445261852a7f610b28dd29146bafda Enc: 88c8bf8f2e1bf0bca22a7c788e971d5402d08a903ec1493769bd837fe153faffe0668e6006788b18069e5837a208345743808c3d326507099c4240601dc90aece3bcb8243b70e57cd2976e040d573b782976144f8206af242b974fc7e27d0b2a7ec491484f9040d5dcdec885b8412904 Sign: 7567a7266cf70080f11b5c0c1aed84e7ff4a173fdded1959d5df8e2c25857371f660844cf7dbb1feda68585b387a6823e4c79ee819833fbe31332428a02ffd96
|
注:gmssl库中的随机数发生器random_hex函数是不符合要求的,其定义如下:
1
| random_hex = lambda x: ''.join([choice('0123456789abcdef') for _ in range(x)])
|
可以看到random_hex有概率为0,而数字签名中的k∈[1, n-1],密钥对生成中的d∈[1, n-2]