详解国密SM2的数字签名

数字签名(又称公钥数字签名)是只有信息的发送者才能产生的别人无法伪造的一段数字串,这段数字串同时也是对信息的发送者发送信息真实性的一个有效证明。它是一种类似写在纸上的普通的物理签名,但是使用了公钥加密领域的技术来实现的,用于鉴别数字信息的方法。一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证。数字签名是非对称密钥加密技术与数字摘要技术的应用。

数字签名的流程

不论采取何种算法进行数字签名,其流程都是差不多的,先说一说签名流程:

国密3 签名 java_数字签名


1.发送者对消息计算摘要值。

2.发送者用私钥对摘要值进行签名得到签名值。

3.发送者将原始消息和签名值一同发给接收者。

再来说一说签名验证流程:

国密3 签名 java_国密3 签名 java_02


1.接收者接收到消息后,拆分出消息和消息签名值A。

2.接收者使用公钥对消息进行运算得到摘要值B。

3.接收者对摘要值B和签名值A进行比较,如果相同表示签名验证成功,否则就是验证失败。

请注意,上面的流程并不是对消息本身签名,而是对消息的摘要值进行签名,这是因为非对称加密算法通常比较慢,而且校验摘要值可以保证消息没有篡改。不论消息有多长,在某种摘要算法下,其摘要值的长度是固定的,对其进行签名速度较快,也比较容易处理。

ECDSA签名算法

目前主流的签名算法有RSA数字签名算法和DSA数字签名算法。RSA数字签名算法和RSA加密算法相似,不同的是,RSA加密算法是公钥加密,私钥解密,而RSA签名算法是私钥签名,公钥验证签名。DSA(Digital Signature Algorithm)数字签名算法生成签名、验证签名的机制和RSA数字签名算法是一样的。这里不详细展开,这些算法都比较成熟,有丰富的资料可参考,一般网络库也都有实现,有兴趣的朋友自行搜索。

DSA算法结合ECC,称为ECDSA数字签名算法。在前面的文章我说过,SM2实际上就是一种椭圆曲线(EC)密码算法,所以这里先详细说说标准的ECDSA算法,然后再说说SM2数字签名算法和ECDSA算法有哪些差别。

在《解读国密非对称加密算法SM2》一文中,我们已经知道,对于椭圆曲线密码算法而言,最重要的是选择一条命名曲线,包括几个重要的参数:p、a、b、G(x,y)和n。而在ECDSA算法中,有三个参数很重要:

1.命名曲线。
2.G,椭圆曲线的基点。
3.n,相当于G基点的打点次数。

在《详解国密SM2的加密和解密》一文中,我们已经谈过密钥对的生成,这里再重复一下:

1.选择一个随机数作为私钥d, 1 < d < n -1
2.基于私钥生成公钥,P(x, y) = d * G(x, y)

签名生成:

下面的步骤中,M是消息,HASH(M)是对消息进行摘要运算。d为私钥,P为公钥。

生成一个随机数k,1 < k < n -1
计算(x, y) = k * G
计算r = x mod n
计算s = (k**-1 * (HASH(M) + d*r)) mod n
得到签名值(r, s)。
详细过程请参考 ANSI X9.62 这份文档(收费文档),上面步骤略去了几个运算值结果检查,另外需要注意上面的运算是大数运算,请不要使用普通的算术运算。

验证签名:

1.将签名转化为两个数r和s,假如r和s小于1或者大于n-1,验证直接失败
2.计算c = (s)**-1 mod n
3.计算u1 = ((HASH(M)) * c) mod n
4.计算u2 = (® * c) mod n
5.计算(x, y) = u1 * G + u2 * P
6。如果r == x mod n,则签名验证成功,否则失败

如果从头实现上面的运算,确实不太容易,因为ECDSA已经相当成熟,所以现在的网络库基本上都有实现。在现有的ECDSA算法基础上修改,增加对SM2签名算法的支持,相对比较容易,下面就说说SM2数字签名算法。

SM2数字签名算法

SM2数字签名算法在《GMT 0003.2-2012 SM2椭圆曲线公钥密码算法第2部分:数字签名算法》这份文档中有详细的描述。其中签名的流程为:

国密3 签名 java_国密3 签名 java_03


从中我们可以看到和标准ECDSA的流程有几点不同:

1.对消息的处理不同,国密签名算法对消息进行了处理,然后才计算摘要。其中 ZA 的计算涉及到命名曲线参数的a、b、G、P
2.A5、A6的运算和ECDSA的第3、4步不一样
3.国密签名过程中,如果出现不合法的值,需要返回到A3步,重新生成随机数,直到值合法。

虽然SM2数字签名算法的计算步骤有所差别,但ECDSA中的基本运算,比如大数的加减乘除、曲线的乘积、取模运算都可以重用,所以实现起来也不是很困难。

验证签名的流程:

国密3 签名 java_区块链_04


如果实现了签名流程,验证签名的流程也比较容易实现,主要是需要关注其中的公式,注意一些细节。

在开发SM2数字签名算法时,我们可以参考附录A中的示例,保证每个步骤的数据能对上,这样最终的结果就