前言
在之前的文章中也后台有关于国密代码实现,逐萌生了把之前理解的国密和密评中的内容整理成文档,尽自己的微薄力量给大家参考和学习。
1 定义
SM2算法定义了两条椭圆曲线,一条基于F§上的素域曲线,一条基于F(2^m)上的拓域曲线,目前使用最多的曲线为素域曲线,本文介绍的算法基于素域曲线上的运算,素域曲线方程定义如下:
y2−x3+ax+b
SM2算法定义了5个默认参数,即有限域F§的规模p,椭圆曲线参数a,b,椭圆曲线的基点G(x,y),与G的阶n。
国密算法标准中给出了对应的默认值,默认值如下:
p:FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF n:FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123 a:FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC b:28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93 Gx:32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7 Gy:BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0 |
#加密强度:256位(私钥长度);
32字节、64 hex
#公私钥长度:公钥长度为64字节(512位)
64字节、128 hex
#支持签名最大数据量及签名结果长度:最大签名数据量长度无限制;签名结果为64字节(但由于签名后会做ASN.1编码,实际输出长度为70-72字节);
#支持加密最大数据量及加密后结果长度:支持最大近128G字节数据长度;加密结果(C=C1C3C2)增加96字节【C1(64字节) + C3(32字节)】(如果首个字节为0x04则增加97字节,实际有效96字节)
2 密钥对
2.1 私钥
SM2私钥是一个大于1且小于n-1的整数(n为SM2算法的阶,其值参见GM/T 0003),简记为k,长度为256位(32字节)
- SM2算法私钥数据格式的ASN.1定义为
SM2PrivateKey::=INTEGER |
2.2 公钥
SM2公钥是SM2曲线上的一个点,由横坐标和纵坐标两个分量来表示,记为(x,y),简记为Q,每个分量的长度为256位,总长度为512位(64字节,不包含公钥标识)。
SM2算法公钥数据格式的ASN.1定义为:
SM2PublicKey::=BIT STRING |
SM2PublicKey为BIT STRING类型,内容为04||X|||Y,其中X和Y分别标示公钥的x分量和y的分量,其长度各位256位。04用来标示公钥为非压缩格式(压缩格式用02标识)
3 数据格式
3.1 加密数据格式
SM2算法加密后的数据格式的ASN.1定义为:
SM2Cipher::= SEQENCE{ XCoordinate INTEGER, --x 分量 32字节(256位) YCoordinate INTEGER, --y 分量 32字节(256位) HASH OCTET STRING SIZE(32), --杂凑值 (256位) CipherText OCTET STRING --密文 等于明文长度 } |
其中,HASH为使用SM3算法对明文数据运算得到的杂凑值,其长度固定为256位。CipherText是与明文等长的密文。因此SM2加密后的密文长度比明文长度增加了97字节(1
字节
04
标识
+ 32
字节
x
分量
+ 32
字节
y
分量
+ 32
字节
Hash
)
3.2 签名数据格式
SM2算法签名数据格式的ASN.1定义为:
SM2Signature::={ R INTEGER, --签名值的第一部分 32字节(256位) S INTEGER --签名值的第二部分 32字节(256位) } |
签名原始数据量长度无限制,签名结果为64字节,但是由于签名后会做ASN.1编码,实际输出长度为70-72字节不等。
- 例子(SM2签名结果):
3045022053158C29EA739622E0109971E6BBC89C068A9C647D190FA08D02D0EA8EE1AEE1022100C8E815C0A688D910E1890C29C639CB5BF53F2464768B132A5DCB9CF68CFC3D7B
可以看到有两个大整数组成,这应该就是签名结果的 R,S ,因此出现如此长度的签名结果是因为DER编码所致。
- 为什么后面是33字节?
因为填充了一个00字节,为啥填充零字节呢?看后面的整数的第一个字节C8 ,转换成二进制是11001000 ,根据整数的特性这个数就是负数了,而这里SM2用到的r,s都是无符号整数,所以要进行编码增加00000000的整数前缀,使得它是个正整数。
- 因此当r,s的最高位都是0位时,不需要填充,它就是等于增加了六个字节的标志字节,累计70字节;
- 当其中一个最高位是1位时,需要填充00,它就是等于增加了七个字节的标志字节,累计71字节;
- 当两个最高位都是1位时,都需要填充00,它就是等于增加了八个字节的标志字节,累计72字节。
总结:密评中签名结果判断第一个字节应该是30 ,第二个字节如果是44 ,后面肯定有两个0220 ;第二个字节如果是45 ,后面出现一个0220,一个022100 ;第二个字节如果是46 ,后面出现两个022100
3.3 密钥对保护数据格式
在SM2密钥对传递时,需要对SM2密钥对进行加密保护。具体的保护方法为:
- 产生一个对称密钥。
- 按对称密码算法标识指定的算法对SM2私钥进行加密,得到私钥的密文。若对称算法为分组算法,则其运算模式为ECB。
- 使用外部SM2公钥加密对称密钥得到对称密钥密文。
- 将私钥密文、对称密钥密文封装到密钥对保护数据中。
上述密钥对保护数据格式实际上就是一个SM2加密信封的数据格式,SM2公钥仅仅是封装在信封内部,依然是裸公钥。
此时有A和B双方进行密钥对传递,B先将自己的SM2公钥传递给A;
A此时要把自己的非对称密钥对安全地传递给B,做法如下:
- A产生一对SM2密钥对,然后A又产生一个对称算法密钥(假定算法为SM4)symK;
- A用symK加密自己的私钥,得到SKCipher,
- A用B的公钥去加密自己的symK,得到对称密钥密文symKCipher;
- A将上述数据封装成一个SM2的加密信封EnvelopA,然后将EnvelopA传递给B。
B收到A发过来的EnvelopA数据后,解开信封过程如下:
- B用自己的私钥解密EnvelopA数据,获取到信封里边的数据。
- B用自己的私钥去解开EnvelopA数据中的对称密钥密文后,拿到对称密钥明文symPlainKey
- B用对称密钥明文数据解开SM2私钥密文,拿到A的私钥明文。
- B拿到了A的SM2公钥/私钥密钥对。
最后,A将自己的SM2密钥对安全传递给B。当然上述传递方式是最基础的,在不同的应用场景下或许有更为复杂的传递方式设计。
4 计算过程
4.1 生成密钥
SM2密钥生成是指生成SM2算法的密钥对的过程,该密钥对包括私钥和与之对应的公钥。其中,私钥的长度为256位,公钥的长度为512位(x和y分量)。
《GMT 0003.1-2012 SM2椭圆曲线公钥密码算法第1部分:总则》
4.2 公钥加密
SM2加密是指使用指定的公开密钥对明文进行特定的加密计算,生成相应密文的过程。该密文只能由该指定公开密钥对应的私钥解密。
详细的计算过程参见GM/T 0003和GM/T 0004。
4.3 私钥解密
SM2解密是指使用指定的私钥对密文进行解密计算,还原对应明文的过程。
详细的计算过程参见GM/T 0003。
4.4 预处理
4.4.1 预处理一
预处理1是指使用签名方的用户身份标识和签名方公钥,通过运算得到Z指的过程。Z值用于预处理2,也用于SM2密钥协商协议。
4.4.2 预处理二
4.5 数字签名
SM2签名是指使用预处理的结果和签名者的私钥,通过签名计算得到签名结果的过程。
说明:第5步若r=0或r+k=n则返回第3步;第6步若s=0则返回第3步。
- 签名者用户A的密钥对包括其私钥dA和公钥PA=[dA]G= (xA,yA)
- 签名者用户A具有长度为entlenA比特的可辨别标识IDA,
- ENTLA是由整数entlenA转换而成的两个字节
- ZA=H256(ENTLA || IDA || a || b || xG || yG|| xA || yA)。
- 待签名的消息为M,
- 数字签名(r,s)
详细计算过程参见GM/T 0003
4.6 签名验证
SM2签名验证是指使用预处理2的结果、签名值和签名者的公钥。通过验签计算确定签名是否通过验证的过程。
- 签名者用户A的密钥对包括其私钥dA和公钥PA=[dA]G= (xA,yA)
- 签名者用户A具有长度为entlenA比特的可辨别标识IDA,
- ENTLA是由整数entlenA转换而成的两个字节
- ZA=H256(ENTLA || IDA || a || b || xG || yG|| xA || yA)。
- 消息为M,数字签名(r,s)
详细计算过程参见GM/T 0003
4.7 密钥协商
密钥协商是在两个用户之间建立一个共享秘密密钥的协商过程,通过这种方式能够确定一个共享秘密密钥的值。
设密钥协商双方为A、B,其密钥对分别为(dA,QA)和(dB,QB),双方需要获得的密钥数据的比特长度为klen。密钥协商协议分为两个阶段。
具体过程见GM/T 0009。