首页 > 工具箱 > 国密算法

国密算法 SM2 / SM3 / SM4

国家密码管理局发布的商用密码算法:SM3 相当于国密版的 SHA-256,SM4 相当于国密版的 AES,SM2 是基于椭圆曲线的公钥算法,对应 RSA 的位置。政务、金融、等保三级以上的系统基本都要求用这一套。本页所有运算都在你的浏览器里完成,密钥、明文、私钥都不会发到服务器。

说明

这三个算法分别对应什么
SM3 是杂凑算法,输出 256 位,用法和 SHA-256 一样,但两者结果完全不同,不能互相替代。SM4 是分组密码,分组和密钥都是 128 位,站位相当于 AES-128。SM2 是椭圆曲线公钥算法,用的是国家指定的 sm2p256v1 曲线(不是 secp256r1),能做加解密也能做签名,安全强度大致对应 RSA-3072,但密钥短、运算快。三者的标准号分别是 GM/T 0004、GM/T 0002、GM/T 0003。
SM4 的密文和别的实现对不上
先核对四件事:一是分组模式,ECB 不需要 IV,CBC 必须双方用同一个 IV;二是填充,国内实现基本都用 PKCS#7,但有些系统用零填充,那种情况下明文末尾的 0x00 会被吃掉;三是密钥的解释方式,同样一串 0123456789abcdef…,有的库当十六进制(16 字节),有的库当 ASCII 文本(32 字节,超长会被截断),本页用上面的「密钥格式」显式区分;四是密文编码,十六进制和 Base64 都很常见。本页的 SM4-CBC 输出与 openssl enc -sm4-cbc 逐字节一致。
SM2 密文的两种排列和 04 前缀
SM2 密文由三段拼成:C1 是临时公钥点(64 字节),C2 是与明文等长的密文,C3 是 32 字节校验值。2012 年的 GM/T 0009 把顺序规定为 C1C3C2,而更早的实现用的是 C1C2C3,两者只是拼接顺序不同,选错了解密会直接失败。另外 C1 是一个椭圆曲线点,按未压缩点格式本应有 04 前缀,前端库(如 sm-crypto)习惯省略,而 Java 侧的 Hutool、BouncyCastle 通常带着。和后端联调解不开时,八成就是这两个开关没对齐——把「带 04」打开或关掉再试一次。
什么是 Z_A,为什么签名要带用户 ID
SM2 签名并不是直接对消息做 SM3,而是先算一个 Z_A = SM3(ENTL ‖ ID ‖ a ‖ b ‖ xG ‖ yG ‖ xA ‖ yA),把曲线参数和签名者公钥揉进去,再对 Z_A ‖ M 做 SM3 得到待签杂凑值。这样同一段消息用不同公钥签出来的杂凑值也不同,能防止一类密钥替换攻击。ID 的国标缺省值就是字符串 1234567812345678,绝大多数系统都用它,除非对方明确要求换。如果你拿到的已经是算好的 32 字节杂凑值,把「杂凑方式」切成第二项即可。
R‖S 和 DER 怎么选
签名的本质是两个 256 位整数 r 和 s。R‖S 就是把它们各补足 64 个十六进制字符直接拼起来,共 128 个字符,前端与部分国产中间件用这种;DER 是 ASN.1 编码的 SEQUENCE { INTEGER r, INTEGER s },长度在 70~72 字节之间浮动,Java 的 BouncyCastle、证书和 TLS 场景用这种。两种编码表达的是同一个签名,可以互转,选错了对方会报「签名格式错误」而不是「验签失败」。
安全提示
本页所有运算都在浏览器里用 JavaScript 完成,密钥不会离开你的电脑,但浏览器环境终究不是安全的密钥容器——生产环境的私钥应该放在加密机或密码卡里,这里生成的密钥对适合用在开发联调、接口调试和教学演示。另外 SM2 加密每次都会用到随机数,所以同一段明文两次加密得到的密文必然不同,这是正常的,不是出错。
相关工具
对称加密 AES/DESRSA 加解密Hash 计算HMAC 计算Base64 编解码
开源致谢
本页的国密运算由 sm-crypto(MIT 协议)提供,已按 GM/T 0004、GM/T 0002 的标准测试向量逐条校验。
已复制