Skip to content

sm2

约 2008 字大约 7 分钟

2025-07-17

1. SM2标准操作

SM2算法是中国商用密码标准之一,它基于椭圆曲线密码学(ECC),提供了数字签名、密钥交换和公钥加密等核心功能。SM2的设计考虑了国家安全需求,旨在提供高强度的数据保护和身份认证。本节将深入探讨SM2的各项标准操作。

1.1 密钥生成

SM2的密钥生成过程是所有密码操作的基础。它涉及以下步骤:

  1. 选择椭圆曲线参数:SM2标准定义了一组特定的椭圆曲线参数,包括曲线方程、基点 GG、阶 nn 和辅助参数。这些参数是公开且固定的,确保了算法的互操作性和安全性。
  2. 生成私钥 dAd_A:私钥 dAd_A 是一个随机生成的大整数,其范围在 [1,n1][1, n-1] 之间。这个私钥必须严格保密,是用户身份的唯一凭证。
  3. 计算公钥 PAP_A:公钥 PAP_A 是通过将私钥 dAd_A 与椭圆曲线的基点 GG 进行标量乘法运算得到的,即 PA=dAGP_A = d_A \cdot G。公钥是公开的,可以安全地分发给任何人。

1.2 加密

SM2加密是一种非对称加密方案,它允许使用接收者的公钥对数据进行加密,而只有持有相应私钥的接收者才能解密。SM2加密过程通常遵循以下步骤:

  1. 随机数生成:选择一个随机数 k[1,n1]k \in [1, n-1]
  2. 计算椭圆曲线点:计算 C1=kGC_1 = k \cdot G
  3. 计算共享秘密:计算 S=hkPBS = h \cdot k \cdot P_B,其中 PBP_B 是接收者的公钥,hh 是一个余因子(通常为1)。如果 SS 是无穷远点,则重新选择 kk
  4. 密钥派生:从 SS 的坐标中派生出对称加密密钥 tt
  5. 异或操作:将明文 MMtt 进行异或操作得到 C2C_2,即 C2=MtC_2 = M \oplus t
  6. 哈希计算:计算明文的哈希值 C3=Hash(x2My2)C_3 = Hash(x_2 || M || y_2),其中 (x2,y2)(x_2, y_2)SS 的坐标。
  7. 形成密文:最终的密文由三部分组成:(C1,C2,C3)(C_1, C_2, C_3)

1.3 解密

SM2解密是加密的逆过程,只有拥有相应私钥 dBd_B 的接收者才能执行。解密过程如下:

  1. 计算共享秘密:使用私钥 dBd_B 和密文中的 C1C_1 计算 S=hdBC1S' = h \cdot d_B \cdot C_1。如果 SS' 是无穷远点,则解密失败。
  2. 密钥派生:从 SS' 的坐标中派生出对称加密密钥 tt'
  3. 异或操作:使用 tt' 对密文 C2C_2 进行异或操作得到明文 M=C2tM' = C_2 \oplus t'
  4. 验证哈希:计算解密得到的明文 MM' 的哈希值 Hash(x2My2)Hash(x_2' || M' || y_2'),并与密文中的 C3C_3 进行比较。如果两者不相等,则解密失败,表明密文被篡改或私钥不匹配。
  5. 输出明文:如果验证通过,则 MM' 就是原始明文。

1.4 签名

SM2数字签名提供消息的完整性和发送者的不可否认性。签名过程涉及以下步骤:

  1. 预处理:对签名消息 MM 进行预处理,包括将用户的身份信息 IDAIDA 和公钥 PAP_A 组合,计算一个 ZA=Hash(ENTLAIDAabxGyGxAyA)Z_A = Hash(ENTL_A || IDA || a || b || x_G || y_G || x_A || y_A),其中 ENTLAENTL_AIDAIDA 的比特长度,a,b,xG,yGa, b, x_G, y_G 是椭圆曲线参数,xA,yAx_A, y_A 是公钥 PAP_A 的坐标。
  2. 计算哈希值:计算待签名消息的哈希值 e=Hash(ZAM)e = Hash(Z_A || M)
  3. 随机数生成:选择一个随机数 k[1,n1]k \in [1, n-1]
  4. 计算椭圆曲线点:计算点 (x1,y1)=kG(x_1, y_1) = k \cdot G
  5. 计算 rr:计算 r=(e+x1)(modn)r = (e + x_1) \pmod n。如果 r=0r=0r+k=nr+k=n,则重新选择 kk
  6. 计算 ss:计算 s=(dA(e+x1)k)(1+dA)1(modn)s = (d_A \cdot (e + x_1) - k) \cdot (1 + d_A)^{-1} \pmod n。如果 s=0s=0,则重新选择 kk
  7. 形成签名:数字签名由一对整数 (r,s)(r, s) 组成。

1.5 验签

验签是验证SM2数字签名有效性的过程,确保消息的完整性和签名者的身份。验证过程如下:

  1. 预处理:与签名过程类似,计算 ZA=Hash(ENTLAIDAabxGyGxAyA)Z_A = Hash(ENTL_A || IDA || a || b || x_G || y_G || x_A || y_A)
  2. 计算哈希值:计算待验证消息的哈希值 e=Hash(ZAM)e = Hash(Z_A || M)
  3. 验证 r,sr, s 范围:检查签名中的 r,sr, s 是否在 [1,n1][1, n-1] 范围内。
  4. 计算 tt:计算 t=(r+s)(modn)t = (r+s) \pmod n。如果 t=0t=0,则验证失败。
  5. 计算椭圆曲线点:计算点 (x1,y1)=sG+tPA(x_1', y_1') = s \cdot G + t \cdot P_A
  6. 计算 RR:计算 R=(e+x1)(modn)R = (e + x_1') \pmod n
  7. 比较:如果 R=rR=r,则签名验证成功;否则,验证失败。

2. SM2 拆分应用

“SM2拆分”通常指的是将SM2算法的某些核心功能或密钥管理环节进行分布式或多方协同处理,以提高系统的安全性、容错性或实现更复杂的信任模型。这种拆分是基于密码学中的多方计算(MPC)和门限密码学概念。

2.1 拆分密钥

第一通信方:

  1. 生成私钥: D1D1 是一个随机生成的大整数,其范围在 [1,n1][1, n-1] 之间。
  2. 生成公钥: 计算在 FqFq 上的逆元 D11D1⁻¹,并计算点 P1=D11GP1 = D1⁻¹ * G, 将 P1P1 发送给第二通信方。

第二通信方:

  1. 生成私钥: D2D2 是一个随机生成的大整数,其范围在 [1,n1][1, n-1] 之间。
  2. 生成公钥: 计算在 FqFq 上的逆元 D21D2⁻¹,并计算最终的公钥 P2=D21P1GP2 = D2⁻¹ * P1 - G,将 P2P2 公钥作为公钥。

2.2 拆分加密

加密则与 SM2 加密方式相同,可以参考 SM2 加密

2.3 拆分解密

第一通信方:

  1. 子私钥生成:第一通信方生成自身的子私钥 D1D1,第二通信方生成自身的子私钥 D2D2
  2. 第一部分解密:第一通信方从密文 CC 中提取出比特串 C1C1,并验证 C1C1 是否为椭圆曲线 EE 上的非无穷远点。若验证通过,计算 T1=D11C1T1 = D1⁻¹ * C1,并将 T1T1 发送给第二通信方。
  3. 第二部分解密:第二通信方接收 T1T1 后,计算 T2=D21T1T2 = D2⁻¹ * T1,并将 T2T2 发送给第一通信方。
  4. 完整解密:第一通信方接收 T2 后,计算 (x2, y2) = T2 - C1 [cite: 1][cite_start]。然后通过预定的密钥派生函数 KDF(x2 || y2, klen) 得到对称解密密钥 t [cite: 1][cite_start]。接着,从密文 C 中提取出比特串 C2 [cite: 1][cite_start],计算 M'' = C2 ⊕ t 得到部分明文 [cite: 1][cite_start]。最后,第一通信方计算 Hash(x2 || M'' || y2) 得到 u [cite: 1][cite_start],并与密文中的 C3 进行比较 [cite: 1][cite_start]。如果 u 等于 C3,则将 M'' 作为完整的明文输出 [cite: 1]。

2.3 拆分签名

  1. 子私钥生成:第一通信方生成自身的子私钥 D1D1,第二通信方生成自身的子私钥 D2D2
  2. 第一方操作:第一通信方生成待签名消息 MM 的消息摘要 ee (通过 Hash(ZM)Hash(Z || M'),其中 ZZ 是共同身份标识) 和第一部分签名 Q1=k1GQ1 = k1 * G ( k1k1 为随机数) 。随后将 eeQ1Q1 发送给第二通信方。
  3. 第二方操作:第二通信方收到 eeQ1Q1 后,生成随机数 k2k2k3k3。计算 Q2=k2GQ2 = k2 * G。然后计算 (x1,y1)=k3Q1+Q2(x1, y1) = k3 * Q1 + Q2,并计算 r=(x1+e)modnr = (x1 + e) mod n。如果 rr 不为 0,则计算 s2=(D2k3)modns2 = (D2 * k3) mod ns3=(D2(r+k2))modns3 = (D2 * (r + k2)) mod n。最后,第二通信方将 rr, s2s2, s3s3 发送给第一通信方。
  4. 完整签名生成:第一通信方接收 rr, s2s2, s3s3 后,根据自身的子私钥 D1D1 和随机数 k1k1,计算 s=((D1k1)s2+D1s3r)modns = ((D1 * k1) * s2 + D1 * s3 - r) mod n。如果 ss 不为0且不等于 nrn-r,则将 (r,s)(r, s) 作为完整签名输出。

2.4 拆分验签

验签则与 SM2 验签方式相同,可以参考 SM2 验签 加密则与 SM2 加密方式相同,可以参考 SM2 加密

贡献者