SM2签名的预处理过程

SM2签名及验证过程中,并不是直接计算被签名数据的摘要,而是要经过专门的预处理过程得到摘要。此过程包含两个阶段的摘要计算:
1)Z = SM3(ENTL || ID || a || b || x_G || y_G || x_A || y_A)
ENTL || ID || a || b || x_G || y_G || x_A || y_A表示签名元素数据的拼接(级联)。
其中,ENTL 是签名者 ID 的位长度,占两个字节;ID是签名者ID,国密标准里定义的缺省签名者ID用UFT_8字符串表示是“1234567812345678”,用十六进制表示是0x31323334353637383132333435363738。所以在缺省情况下,ENTL值是0x0080.
a, b, x_G, y_G 都是SM2算法标准中给定的值。a和b是椭圆曲线y=x+ax+b的系数,x_G, y_G是SM2算法选定的基点的坐标。上述参数都是固定值:
a=0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC
b=0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93
x_G= 0x32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7
y_G=0xBC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0
x_A || y_A就是公钥两部分值的拼接,注意,没有0x04的部分;
将上述各元素拼接值进行SM3运算,得到结果Z。
2) H=SM3(Z || M)
Z是第一步运算得到的摘要,M是签名的原文,将两者拼接,再进行SM3摘要运算。得到的摘要就是预处理得到的结果,将用于后续的签名及验证运算。
另外,由于在运算过程中我们经常要用十六进制的形式表示数据,因此需要进行十六进制字符串与字节数组之间的转换,方法很多,这里推荐一种常用的(VB源码):
'十六进制字符串转换成字节数组

Public Function HexStringToByteArray(HexString As String, Optional BigEndian As Boolean = True) As Byte()
	Dim datalen As Long
	Dim bdata() As Byte
	datalen = Len(HexString)
	If ((datalen Mod 2) = 1) Or (datalen = 0) Then
		Err.Raise -10001, , "字符个数应为大于1的偶数"
	End If
	ReDim bdata(datalen / 2 - 1)
	Dim i As Long
	If BigEndian Then
		For i = LBound(bdata) To UBound(bdata)
			bdata(i) = CByte("&H" & Mid(HexString, i * 2 + 1, 2))
		Next i
	Else
		For i = LBound(bdata) To UBound(bdata)
			bdata(UBound(bdata) - i + LBound(bdata)) = CByte("&H" & Mid(HexString, i * 2 + 1, 2))
		Next i
	End If
	HexStringToByteArray = bdata
End Function
'字节数组串转换成十六进制字符
Public Function ByteArrayToHexString(ByteArray() As Byte, Optional BigEndian As Boolean = True) As String
	Dim datalen As Long
	datalen = UBound(ByteArray) - LBound(ByteArray) + 1
	Dim i As Long
	Dim hstr As String
	Dim hexchr As String
	If BigEndian Then
		For i = LBound(ByteArray) To UBound(ByteArray)
			hexchr = Hex(ByteArray(i))
			If Len(hexchr) = 1 Then
				hstr = hstr & "0" & hexchr
			Else
				hstr = hstr & hexchr
			End If
		Next i
	Else
		For i = UBound(ByteArray) To LBound(ByteArray) Step -1
			hexchr = Hex(ByteArray(i))
			If Len(hexchr) = 1 Then
				hstr = hstr & "0" & hexchr
			Else
				hstr = hstr & hexchr
			End If
		Next i
	End If
	ByteArrayToHexString = hstr
End Function

上述转换过程都是默认大端优先。

### Python 实现 SM2 签名与验签 以下是基于 Python 的 SM2 签名和验签的代码示例。该实现依赖于 `gmssl` 库,这是一个支持国密标准(包括 SM2 和 SM4)的开源库。 #### 安装 gmssl 库 在运行代码之前,请先通过 pip 安装所需的库: ```bash pip install gmssl ``` #### 示例代码 以下是一个完整的 Python 代码示例,展示如何使用 `gmssl` 进行 SM2 签名和验签: ```python from gmssl import sm2, func # 初始化SM2加密实例 public_key = "0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798" private_key = "C9CAFAD54B3ECCACEAE54BFEA5EAEBDFADE8BAA53333BEE1B33BECDD3FDAB4B3" sm2_crypt = sm2.CryptSM2(public_key=public_key, private_key=private_key) # 待签名的数据 data = b"Hello, this is a test message!" # 对数据进行哈希处理 hash_data = func.bytes_to_list(func.hash_sm3(data)) # 签名过程 signature = sm2_crypt.sign(hash_data) print(f"Signature: {func.list_to_bytes(signature).hex()}") # 验签过程 verify_result = sm2_crypt.verify(sign=signature, data_hash=hash_data) if verify_result: print("Verification succeeded!") else: print("Verification failed!") ``` #### 关键点解析 1. **公钥与私钥** 上述代码中的 `public_key` 和 `private_key` 是随机生成的一对 SM2 密钥[^1]。实际应用中应确保这些密钥的安全存储。 2. **数据哈希化** 在执行签名前,通常需要对待签名数据进行哈希处理。这里使用的是国密标准的 SM3 哈希算法[^4]。 3. **签名与验签逻辑** - 签名阶段调用了 `CryptSM2` 类的 `sign` 方法,并传入经过哈希化的消息摘要。 - 验签阶段则通过 `verify` 方法校验签名的有效性,最终返回布尔值表示结果。 --- ### 注意事项 - 如果输入数据未经过预处理,则需满足固定长度要求(如 32 字节)。这取决于具体应用场景的需求。 - 在生产环境中,建议采用更安全的方式管理密钥,例如硬件安全模块(HSM)或专用密钥管理系统[^3]。 --- #### 输出样例 假设上述代码正常运行,可能得到如下输出: ``` Signature: ffaa...bbee Verification succeeded! ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_45303938

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值