[原]国密SM2算法

版权声明:本文为博主原创文章,转载请注明来源!获取更新内容请关注我的开源项目:https://github.com/zcc0721/MasterBlockchain https://blog.csdn.net/u013137970/article/details/84573200

1 前言

比原链的智能合约支持国密算法的函数。SM2是国密标准的椭圆曲线加密算法,遵循以下SM2国家标准:

  • GB/T 32918.1-2016
  • GB/T 32918.2-2016
  • GB/T 32918.3-2016
  • GB/T 32918.4-2016
  • GB/T 32918.5-2017
  • GB/T 35275-2017
  • GB/T 35276-2017

椭圆曲线算法那公钥密码所基于的曲线性质:椭圆曲线多倍点运算构成一个单向函数。在多倍点运算中,已知多倍点与基点,求解倍数的问题称为椭圆曲线离散对数问题。对于一般椭圆曲线的离散对数问题,目前只存在指数级计算复杂度的求解方法。与大数分解问题及有限域上离散对数问题相比,椭圆曲线离散对数问题的求解难度要大得多。因此,在相同安全程度要求下,椭圆曲线密码较其他公钥密码所需的秘钥规模要小得多。

数字签名算法由一个签名者对数据产生数字签名,并由一个验证者验证签名的可靠性。每个签名者都有一个公钥和一个私钥,其中私钥用于产生签名,验证者用签名者的公钥验证签名。在签名的生成过程之前,要用密码杂凑算法对 ZAZ_A

2 基础参数

SM2的曲线方程为 y2=x3+ax+b\displaystyle y^2 = x^3 + ax + b

  • aa:0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC
  • bb:0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93
  • pp:0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF

私钥长度:32字节。

公钥长度:SM2非压缩公钥格式字节串长度为65字节,压缩格式长度为33字节,若公钥y坐标最后一位为0,则首字节为0x02,否则为0x03。非压缩格式公钥首字节为0x04。

签名长度:64字节。

3 密钥对生成

SM2密钥生成是指生成SM2算法的密钥对的过程,该密钥对包括私钥和与之对应的公钥。

  • 输入:无
  • 输出:
    • k:SM2PrivateKey,SM2私钥
    • Q:SM2PublicKey,SM2公钥
  1. 用随机数发生器产生整数 d∈[1,n−2]\displaystyle d\in[1,n-2]
  2. GG 为基点,计算点 P=(xP,yP)=[d]G\displaystyle P=(x_P,y_P)=[d]G

则私钥是dd,公钥为PP。

4 签名算法

4.1 预处理1

预处理1是指使用签名方的用户身份标识和签名方公钥,通过运算得到Z值的过程。Z值用于预处理2。

  • 输入:
    • ID:字符串,用户身份标识
    • Q:SM2PublicKey,用户的公钥
  • 输出:
    • Z:字节串,预处理1的输出
  • 计算公式:Z=SM3(ENTL∣∣ID∣∣a∣∣b∣∣xG∣∣yG∣∣xA∣∣yA)Z=SM3(ENTL||ID||a||b||x_G||y_G||x_A||y_A)
  • 参数说明:
    • ENTLENTL:为由2个字节标识的ID的比特长度;
    • IDID:为用户身份标识。无特殊约定的情况下,用户身份标识ID的长度为16字节,其默认值从左至右依次为:0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38。
    • a,ba,b:为系统曲线参数;
    • xG, yG\displaystyle x_G,\ y_G
    • xA, yA\displaystyle x_A,\ y_A

4.2 预处理2

预处理2是指使用Z值和待签名消息,通过SM3运算得到杂凑值H的过程。杂凑值H用于SM2数字签名。

  • 输入:
    • Z:字节串,预处理2的输入
    • M:字节串,待签名消息
  • 输出:
    • H:字节串,杂凑值
  • 计算公式:H=SM3(Z∣∣M)\displaystyle H=SM3(Z||M)

4.3 生成签名

SM2签名是指使用预处理2的结果和签名者的私钥,通过签名计算得到签名结果的过程。

  • 输入:
    • d:SM2PrivateKey,签名者私钥
    • H:字节串,预处理2的结果
  • 输出:
    • sign:SM2Signature,签名值

设待签名的消息为M,为了获取消息M的数字签名 (r,s)(r,s),作为签名者的用户A应实现以下运算步骤:

  1. 置 M‾=ZA∣∣M\displaystyle \overline{M}=Z_A||M
  2. 计算 e=Hv(M‾)\displaystyle e=H_v(\overline{M})
  3. 用随机数发生器产生随机数 k∈[1,n−1]\displaystyle k\in[1,n-1]
  4. 计算椭圆曲线点 (x1,y1)=[k]G\displaystyle (x_1,y_1)=[k]G
  5. 计算 r=(e+x1)mod n\displaystyle r=(e+x_1) mod \ n
  6. 计算 s=((1+dA)−1⋅(k−r⋅dA))mod n\displaystyle s=((1+d_A)^{-1}\cdot (k-r \cdot d_A)) mod\ n
  7. 将 r,sr, s 转化为字节串。

消息M的签名为(r,s)(r, s)。

4.4 签名验证

SM2签名验证是指使用预处理2的结果、签名值和签名者的公钥,通过验签计算确定签名是否通过验证的过程。

  • 输入:
    • H:字节串,预处理2的结果
    • sign:SM2Signature,签名值
    • Q:PublicKey,签名者的公钥
  • 输出:为真表示验证通过,为假表示验证不通过。

为了检验收到的消息 M及其数字签名(r,s)(r, s),作为验证者的用户B应实现以下运算步骤:

  1. 检验 r∈[1,n−1]\displaystyle r\in[1,n-1]
  2. 检验 s∈[1,n−1]\displaystyle s\in[1,n-1]
  3. 置 M‾=ZA∣∣M\displaystyle \overline{M}=Z_A||M
  4. 计算 e=Hv(M‾)\displaystyle e=H_v(\overline{M})
  5. 将 r,sr,s 的数据类型转化为整数,计算 t=(r+s)mod n\displaystyle t=(r+s) mod \ n
  6. 计算椭圆曲线点 (x1,y1)=[s]G+[t]PA\displaystyle (x_1,y_1)=[s]G+[t]P_A
  7. 将 x1\displaystyle x_1

4.5 签名验证原理

[s]G+[t]PA=sG+(r+s)PA=sG+(r+s)dAG=sG+sdAG+rdAG=(1+dA)sG+rdAG=(1+dA)(1+dA)−1(k−rdA)G+rdAG=(k−rdA)G+rdAG=kG−rdAG+rdAG=kG=(x1,y1)\displaystyle \begin{aligned} [s]G+[t]P_A &=sG+(r+s)P_A\\ &=sG+(r+s)d_AG\\ &=sG+s d_AG+rd_AG\\ &=(1+d_A)sG+rd_AG\\ &=(1+d_A)(1+d_A)^{-1}(k-rd_A)G+rd_AG\\ &=(k-rd_A)G+rd_AG\\ &=kG-rd_AG+rd_AG\\ &=kG\\ &=(x_1,y_1) \end{aligned}

5 参考资料

https://blog.csdn.net/u013137970/article/details/84573200

标签