29

详解国密 SM2 的加密和解密

 4 years ago
source link: https://mp.weixin.qq.com/s/Axj_oVvV2g-xSTLXO15c8w
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

在上一篇文章《 解读国密非对称加密算法SM2 》介绍了国密非对称算法SM2,在文章中说到,如果现有的网络库中已经实现ECC算法,只需加入SM2命名曲线的参数即可。这对于ECDHE密钥协商和ECDSA数字签名这两种用途而言确实是足够的。现有的网络库,很少将ECC算法直接用于加密和解密。但在实现ECC_SM4_SM3这个密码套件中,在密钥交换过程中,存在客户端将Pre-Master Secret使用 SM2 公钥加密后传给服务器端的步骤。所以我们需要实现 SM2 的加密和解密。

如何使用 SM2 算法进行加密和解密,可以参考的资料是《GMT 0003.4-2012 SM2椭圆曲线公钥密码算法第4部分:公钥加密算法》。但这份文档有些地方描述的并不是很清楚,实现起来也是很头疼,在参考了GmSSL开源项目的源码之后,总算把这个过程梳理清楚了。先总结一下,把其中容易出错的位置重点说明一下,供大家参考。

先来看看国密文档中关于加密流程的描述:

MBvuQbR.png!web

  1. 在A1步骤中,需要注意不能使用C语言中简单的随机数函数,因为这里 k 是一个很大的数字,有32字节,在GmSSL是用 BIGNUM 结构来表示的。在一般网络库中都会定义这种大整数类型,也会提供了随机函数发生器。

  2. 在A2步骤中,一般实现了ECC算法的网络库都实现了 [k]G 这种运算,找到使用即可。将C1转化为比特串,需要考虑CPU大小端的问题,通常网络库有现成的函数。

  3. 在A3步骤中,刚开始看文档没明白 h 值是什么,后来才理解到这就是曲线参数的 cofactor,而且这个步骤主要是验证公钥PB的有效性,略过也没问题。

  4. 在A5步骤中,有个KDF函数需要实现。KDF函数的流程如下,其中的Hv函数请使用SM3:

VJnaMjQ.png!web

  1. A7步骤的Hash也采用SM3

  2. 在最后拼接 C1 || C3 || C2 步骤,并不是把这些字节拼接起来就完事,我吃过大亏。因为在解密步骤中,还需要用到 x1、y1、C3、C2这几个参数,如果拼接成一个bit串,接收方如何拆分?如果我们内部使用,当然可以根据它们各自的长度(对于指定SM2曲线和SM3哈希算法,x1, y1, C3的长度是固定的)来拆分,但这样不够灵活,万一换了命名曲线或哈希算法呢?在文档中没有找到说明,但我研究了GmSSL的源码,才弄明白要采用ASN.1 DER编码,这样接受方就可以通过DER解码,分别拿到x1、y1、C3、C2参数值。关于DER编码解码,请参考相关的资料,一般网络库都会提供DER编解码的函数,我们只要调用就可以了。

最后这一步,要是只看这份文档,就会掉进一个大坑。我在本地实现了SM2的加密和解密,使用 《GMT 0003.4-2012》文档附录中的数据进行测试,也都通过,但在与第三方服务器端对接时,总是解密失败,后来才发现是因为这个原因。

国密文档中关于解密流程的描述:

e2AnEjn.png!web

实现了加密流程后,解密流程的实现就简单了,这里不再过多描述。

《GMT 0003.4-2012》文档附录A中的测试数据非常有用,有每个步骤的计算结果,可用于排查哪个步骤实现出现问题,在开发中要充分利用。

小结

非对称加密算法通常很少直接用于数据的加密和解密,主要是考虑到其速度远低于对称加密算法。在ECC_SM4_SM3密码套件中,SM2用于密钥交换(客户端生成Pre-Master Secret,加密后传输给服务器端)。当然,如果在程序中直接使用SM2加密信用卡卡号之类的小数据也是可以的。

如果大家有什么问题,欢迎交流。

qiUN3iI.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK