SM2一般用到的或者第三方提供的公钥都是压缩过的,长度为66个长度,既33字节。
格式如下,保密期间秘钥内容用*代替了,从02到....3F3B共33字节。66个长度
06:028736002931F****************43986E66********D4FF11E9936A6CB9A3F3B
14:03017459D79C*****************88D6E6D********DDF979E40170F61308FAB
15:0286933F6EF6*****************C306FCD7545CEB4DDD214049001657D1C0DE
17:02D5795D52E******************48F282DCAD5EEF129ED2DF1D8FF806626FC0
但是封装后的接口如:
int SM2_do_verify(unsigned char* message, int len, unsigned char* xA, unsigned char* yA, unsigned char* r, unsigned char* s)
那么如何调用呢?
压缩公钥中,哪个是xA? 哪个是yA? xA和yA不应该有32个字节吗?怎么提供的压缩公钥是33字节?
以下解答这些疑问。
前面的 06: ,17:为公钥的索引。且为16机制的。 0x17 == 23
提供的33字节的压缩公钥,最面前的02和03不是公钥的内容,因此排除第一个字节,后面的32字节才是真正的压缩公钥。
压缩公钥如何解压出xA和yA呢?其实xA没有压缩,排除前面的02或03,后面的32字节就是xA. yA是根据xA算出来的。
调用以下接口即可:
int SM2_get_Py(unsigned char y0, unsigned char Px[],unsigned char Py[])
这个y0参数传啥?是个什么意思?
y0代表公钥y坐标的最后一位。有两个取值,是0还是1 。
如果公钥X压缩码为02,则这个取值传0.如果公钥X压缩码为03,则这个值取1.
y0取0或取1涉及算法内部的一些翻转操作,不能传错。
这样调用key_get_y(&pubkeyX[1], 32, pubkeyY, 32, bc) 就获取到了y坐标公钥啦。
其实y公钥就是从X获取到的。X是谁呢,就是那串压缩公钥,原封不动。
至于内部具体怎么解压的,看代码,能看出点儿端倪。
SM2的曲线方程为y2 = x3 + ax + b,其中知道了x当然就能求出y。这里的x就是提供的压缩公钥。
r,s为数字签名(r, s),相当于这个公式里的a和b吧。
只不过里面涉及了大数运算,要不是有大数运算,应该很好理解吧。用上了大数运算,就得借助openssl或miral大数库了。
Function: SM2_get_Py
Description: SM2 public key decompress to get Py
Input: public key Px,y0(Py last right bit)
Output: pubKey y // pubKey=[priKey]G
Return: 0: sucess
int SM2_get_Py(unsigned char y0, unsigned char Px[],unsigned char Py[])
{
big x_3;
big x,y;
big tmp;
big y2;
miracl *mip=mirsys(10000,16);
mip->IOBASE=16;
SM2_Init();
x_3=mirvar(0);
x=mirvar(0);
y=mirvar(0);
y2=mirvar(0);
tmp=mirvar(0);
bytes_to_big(SM2_NUMWORD,Px,x);
//printf(x);
power (x, 3, p, x_3); //x_3=x^3 mod p
multiply (x, a,x); //x=a*x
divide (x, p, tmp); //x=a*x mod p , tmp=a*x/p
add(x_3,x,x); //x=x^3+ax
add(x,b,x); //x=x^3+ax+b
divide(x,p,tmp); //x=x^3+ax+b mod p
if(!sqroot(x, p, y))
{ return 1; }
big_to_bytes(SM2_NUMWORD,y,Py, TRUE);
if( ( y0 & 0x01) != (Py[31] & 0x01) )
{
//y0 = 0;
subtract(p, y, y2);
big_to_bytes(SM2_NUMWORD,y2,Py, TRUE);
printf("-----------------------------------------------------------------py key step 2\n");
}
return 0;
}
SM2对应RSA, SM4对应 AES或 3DES,SM3对应SHA或MD5哈希算法。
其实SM2 和3和4 功能和作用和RSA,3DES,SHA等是一样的,只是实现了国产化替代。
SM1则貌似没有公开或者要求只能由硬件实现,资料很少。算法安全保密强度及相关软硬件实现性能与 AES 相当,该算法不公开,仅以 IP 核的形式存在于芯片中。
以下内容,摘自网络,感兴趣的可以了解下算法原理。
作者:岛叔
链接:https://www.zhihu.com/question/290243441/answer/469697191
来源:知乎
在金融领域目前主要使用公开的SM2、SM3、SM4三类算法,分别是非对称算法、哈希算法和对称算法。
SM2算法:SM2椭圆曲线公钥密码算法是我国自主设计的公钥密码算法,包括SM2-1椭圆曲线数字签名算法,SM2-2椭圆曲线密钥交换协议,SM2-3椭圆曲线公钥加密算法,分别用于实现数字签名密钥协商和数据加密等功能。SM2算法与RSA算法不同的是,SM2算法是基于椭圆曲线上点群离散对数难题,相对于RSA算法,256位的SM2密码强度已经比2048位的RSA密码强度要高。
SM3算法:SM3杂凑算法是我国自主设计的密码杂凑算法,适用于商用密码应用中的数字签名和验证消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。为了保证杂凑算法的安全性,其产生的杂凑值的长度不应太短,例如MD5输出128比特杂凑值,输出长度太短,影响其安全性SHA-1算法的输出长度为160比特,SM3算法的输出长度为256比特,因此SM3算法的安全性要高于MD5算法和SHA-1算法。
SM4算法:SM4分组密码算法是我国自主设计的分组对称密码算法,用于实现数据的加密/解密运算,以保证数据和信息的机密性。要保证一个对称密码算法的安全性的基本条件是其具备足够的密钥长度,SM4算法与AES算法具有相同的密钥长度分组长度128比特,因此在安全性上高于3DES算法。
SM2、SM3及SM4加密标准
转自:https://wenku.baidu.com/view/108aad77710abb68a98271fe910ef12d2bf9a945.html
- 概述
- SM2椭圆曲线公钥密码算法加密标准
SM2算法就是ECC椭圆曲线密码机制,但在签名、密钥交换方面不同于ECDSA、ECDH等国际标准,而是采取了更为安全的机制。SM2-1椭圆曲线数字签名算法,SM2-2椭圆曲线密钥交换协议,SM2-3椭圆曲线公钥加密算法,分别用于实现数字签名密钥协商和数据加密等功能。SM2算法与RSA算法不同的是,SM2算法是基于椭圆曲线上点群离散对数难题,相对于RSA算法,256位的SM2密码强度已经比2048位的RSA密码强度要高。
椭圆曲线算法公钥密码所基于的曲线性质:椭圆曲线多倍点运算构成一个单向函数。在多倍点运算中,已知多倍点与基点,求解倍数的问题称为椭圆曲线离散对数问题。对于一般椭圆曲线的离散对数问题,目前只存在指数级计算复杂度的求解方法。与大数分解问题及有限域上离散对数问题相比,椭圆曲线离散对数问题的求解难度要大得多。因此,在相同安全程度要求下,椭圆曲线密码较其他公钥密码所需的秘钥规模要小得多。
- SM3哈希算法加密标准
SM3是一种密码散列函数标准。密码散列函数是散列函数的一种。它被认为是一种单向函数,也就是说极其难以由散列函数输出的结果,回推输入的数据是什么。这种散列函数的输入数据,通常被称为消息,而它的输出结果,经常被称为消息摘要。
SM3适用于商用密码应用中的数字签名和验证消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。为了保证杂凑算法的安全性,其产生的杂凑值的长度不应太短,例如MD5输出128比特杂凑值,输出长度太短,影响其安全性SHA-1算法的输出长度为160比特,SM3算法的输出长度为256比特,因此SM3算法的安全性要高于MD5算法和SHA-1算法。
一个理想的密码散列函数应该有这些特性:对于任何一个给定的消息,它都很容易就能运算出散列数值;难以由一个已知的散列数值,去推算出原始的消息;在不更动散列数值的前提下,修改消息内容是不可行的;对于两个不同的消息,它不能给与相同的散列数值。
- SM4分组密码算法加密标准
SM4算法是一个分组对称密钥算法,明文、密钥、密文都是16字节,加密和解密密钥相同。加密算法与密钥扩展算法都采用32轮非线性迭代结构。解密过程与加密过程的结构相似,只是轮密钥的使用顺序相反。
SM4用于实现数据的加密/解密运算,以保证数据和信息的机密性。要保证一个对称密码算法的安全性的基本条件是其具备足够的密钥长度,SM4算法与AES算法具有相同的密钥长度分组长度128比特,因此在安全性上高于3DES算法。
- SM2加密标准
- SM2基本原理
- 基础参数
SM2的曲线方程为y2 = x3 + ax + b,其中:
- a: 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC
- b: 0x28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93
- c: 0xFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF
- 私钥长度:32字节
- 公钥长度:SM2非压缩公钥格式字节串长度为65字节,压缩格式长度为33字节,若公钥y坐标最后一位为0,则首字节为0x02,否则为0x03。非压缩格式公钥首字节为0x04。
- 签名长度:64字节
- 密钥对生成
SM2密钥生成是指生成SM2算法的密钥对的过程,该密钥对包括私钥和与之对应的公钥。
- 输入:一个有效的Fq(q=p且p为大于3的素数,或q=2m)上椭圆曲线系统参数的集合。
- 输出:与椭圆曲线系统参数相关的一个密钥对(d, P)
k: SM2PrivateKey,SM2私钥
Q: SM2PublicKey,SM2公钥
用随机数发生器产生整数 d∈[1, n-2];
G为基点,计算点P=(xP, yP)=[d]G
密钥对是(d, P),其中d为私钥,P为公钥
- 签名算法
- 预处理1
预处理1指使用签名方的用户身份标识和签名方公钥,通过运算得到Z值的过程,Z值用于预处理2。
- 输入:ID 字符串,用户身份标识;Q SM2PublicKey,用户的公钥。
- 输出:Z 字节串,预处理1的输出。
- 计算公式:Z=SM3(ENTL||ID||a||b||xG||yG||xA||yA)
- 参数说明:
ENTL: 由两个字节标识的ID的比特长度;
ID: 用户身份标识,一般情况下,其长度为16字节,默认值从左至右依次是:0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38。
a, b: 为系统曲线参数;
xG, yG为基点;xA, yA为用户的公钥。
- 预处理2
预处理2是指使用Z值和待签名消息,通过SM3运算得到杂凑值H的过程。杂凑值H用户SM2数字签名。
- 输入:Z 字节串;M 字节串,待签名消息
- 输出:H 字节串,杂凑值
- 计算公式:H=SM3(Z||M)
- 生成签名
SM2签名是指使用预处理2的结果和签名者的私钥,通过签名计算得到签名结果的过程。
- 输入:d: SM2PrivateKey,签名者私钥;H 字节串,预处理2的结果
- 输出:sign: SM2Signature,签名值
设待签名的消息为M,为了获取消息M的数字签名(r,s)(r,s)(r,s),作为签名者的用户A应实现以下运算步骤:
置M’=ZA||M;计算e=Hv(M’),将e的数据类型转化为整数;用随机数发生器产生随机数k∈[1, n-1];计算椭圆曲线点(x1, y1)=[k]G,将x1的数据类型转化为整数;计算r=(e+x1)mod n,若r=0或r+k=n则返回第3步;计算s=((1+dA)-1*(k-r*dA))mod n,若s=0则返回第3步;将r, s转化为字节串。消息M的签名为(r, s)。
- 签名验证
- 输入:H:字节串,预处理2的结果;sign:SM2Signature,签名值;Q:PublicKey,签名者的公钥
- 输出:为真表示验证通过,为假表示验证不通过。
为了检验收到的消息 M及其数字签名(r, s),作为验证者的用户B应实现以下运算步骤:
- 检验r∈[1,n-1],是否成立,若不成立则验证不通过;
- 检验s∈[1,n-1],是否成立,若不成立则验证不通过;
- 置M’=ZA||M;
- 计算e=Hv(M’),将e的数据类型转化为整数;
- 将r,s的数据类型转化为整数,计算t=(r+s)mod n,若t=0,则验证不通过;
- 计算椭圆曲线点(x1, y1)=[s]G+[t]PA;
- 将x1的数据类型转化为整数,计算R=(e+x1)mod n,检验R=r是否成立,若成立则验证通过;否则验证不通过。
- SM2的应用
SM2在固件安全中的应用:
固件控制着整个存储系统的正常运行,倘若非法人员可以随意导入固件、修改固件,那么数据也将完全暴露,因此保护数据存储安全的首要一点就是要确保固件在导入、保存和执行过程中的安全。
在固件导入过程中使用SM2算法进行验签,其中用到的公钥保存在主控芯片内部,私钥由受信用的固件厂商保存。对于要导入的固件,需要使用私钥对其进行签名,将签名和固件一起导入到盘片,带有签名的固件下载到缓存RAM后,再用公钥进行SM2验签。只有使用合法私钥签名的固件才能通过验签,成功导入,没有签名或者使用非法私钥签名的固件无法通过验签而被丢弃。如此,拥有合法私钥的用户才拥有固件的导入权限,从源头上确保了盘片内部固件的合法性。
- 对比SM2与同类型算法
RSA算法数学原理简单,在工程应用中比较易于实现,但它的单位安全强度相对较低。目前国际上公认的对于RSA算法最有效的攻击方法,即一般数域筛方法去破译和攻击RSA算法,它的破译或求解难度是亚指数级的。
SM2算法的数学理论非常深奥复杂,在工程应用中比较难于实现,但它的单位安全强度相对较高。用国际上公认的对于SM2算法最有效的攻击方法Pollard rho去破译攻击SM2算法,它的破译或求解难度基本上是指数级的。SM2算法的单位安全强度高于RSA算法。一般认为当SM2密码体制的密钥长度为160比特时,其安全性相当于RSA使用1024比特密钥长度,密钥短意味着更短的处理时间和密钥存储空间。
SM2具有安全性能更高、计算量小、处理速度快、存储空间占用小、带宽要求低和便于密码管理等优点,能在整体上提高加密过程中的速度与安全性。
- SM3加密标准
- SM3基本原理
对长度为l(l < 2^64) 比特的消息m, SM3杂凑算法经过填充和迭代压缩,生成杂凑值,杂凑值长度为256比特。
- 填充
假设消息m 的长度为l 比特。首先将比特“1”添加到消息的末尾,再添加k 个“0”, k是满足l + 1 + k ≡ 448mod512 的最小的非负整数。然后再添加一个64位比特串,该比特串是长度l的二进制表示。填充后的消息m’的比特长度为512的倍数。
- 迭代
将填充后的消息m’按512比特进行分组:m’=B(0)B(1)…B(n-1),其中n=(l+k+65)/512。对m’按下列方式迭代:
FOR i=0 TO n-1
V(i+1)=CF(V(i), B(i))
ENDFOR
其中CF是压缩函数,V(0)为256比特初始值IV,B(i)为填充后的消息分组,迭代压缩的结果为V(n)。
- 消息扩展
将消息分组B(i)按以下方法扩展生成132个字W0, W1,…, W67 , W0’, W1’, …, W63’,用于压缩函数CF:
将消息分组B(i)划分为16个字W0, W1, …, W15
FOR j=16 TO 67
WjßP1(Wj-16⊕Wj-9⊕(Wj-3<<<15))⊕(Wj-13<<<7)⊕Wj-6
ENDFOR
FOR j=0 TO 63
W’j=Wj⊕Wj+4
ENDFOR
- 压缩函数
令A,B,C,D,E,F,G,H为字寄存器,SS1,SS2,TT1,TT2为中间变量,压缩函数Vi+1=CF(V(i), B(i)), 0<=i<=n-1,计算过程如下:
FOR j=0 TO 63
SS1ß((A<<<12)+E+(Tj<<<j))<<<7
SS2ßSS1⊕(A<<<12)
TT1ßFFj(A,B,C)+D+SS2+W’j
TT2ßGGj(E,F,G)+H+SS1+Wj
DßC
CßB<<<9
BßA
AßTT1
HßG
GßF<<<19
FßE
EßP0(TT2)
ENDFOR
V(i+1)ßABCDEFGH⊕V(i)
- 杂凑值
ABCDEFGHßV(n)
输出256比特的杂凑值y=ABCDEFGH。
- SM3的应用
SM3在芯片中的应用:
芯片中有sm3函数的入口,每次只能输入8个字节(64位)的16进制数,所以要把文件拆分成N*8字节,并转为16进制,需要执行sm3函数N次
前面N-1次和最后一次执行函数所用的报文不同,前面N-1次中报文的p1=01(没有返回杂凑值,但是函数中记录下迭代中间结果,作为下一次迭代输入,不输出),最后一次报文的p1=02,(结合上面迭代中间值,输出最终杂凑值)。
- 对比SM3与同类型算法
摘要函数在密码学中具有重要的地位,被广泛应用在数字签名,消息认证,数据完整性检测等领域。摘要函数通常被认为需要满足三个基本特性:碰撞稳固性,原根稳固性和第二原根稳固性。2005年,Wang等人给出了MD5算法和SHA-1算法的碰撞攻击方法,现今被广泛应用的MD5算法和SHA-1算法不再是安全的算法。
SM3算法适用于商用密码应用中的数字签名和验证,是在SHA-256基础上改进实现的一种算法。SM3算法采用Merkle-Damgard结构,消息分组长度为512位,摘要值长度为256位。SM3算法的压缩函数与SHA-256的压缩函数具有相似的结构,但是SM3算法的设计更加复杂,比如压缩函数的每一轮都使用2个消息字。SM3的安全性相对较高。
- SM4加密标准
- SM4基本原理
- 参数产生
字节由8位二进制数表示,字由32位二进制数表示;S盒为固定的8比特输入和输出置换;加密密钥长度为128bit,表示为MK=(MK0,MK1,MK2,MK3),其中MKi (i=0,1,2,3)为字。轮密钥表示为rki(i=0,1,2.....,31)为字。FK=(FK0,FK1,FK2,FK3)为系统参数,CK=(CK0,CK1,.....,CK31)为固定参数,都为字。
- 轮函数
整体的加密函数为:
Xi+4=F(Xi, Xi+1, Xi+2, Xi+3, rki)=Xi⊕T(Xi+1⊕Xi+2⊕Xi+3⊕rki)
其中T为一个合成置换,由非线性变换和线性变换复合而成。
- 非线性变换由4个平行的S盒构成,S盒的数据均采用16进制。
- 线性变换公式如下,其中B为非线性变换得到的字
C=L(B)=B⊕(B<<2)⊕(B<<10)⊕(B<<18)⊕(B<<24)
- 密钥扩展
已知加密密钥MK=(MK0,MK1,MK2,MK3),系统参数FK=(FK0,FK1,FK2,FK3),固定参数CK=(CK0,CK1,.....,CK31)。rki为轮密钥,轮密钥由加密密钥生成。
首先(K0, K1, K2, K3)=(MK0⊕FK0, MK1⊕FK1, MK2⊕FK2, MK3⊕FK3),然后对i=0,1,2,…,31:rki=Ki+4=Ki⊕T’(Ki+1⊕Ki+2⊕Ki+3⊕CKi),该变换与加密中的T变换基本相同,只是将其中的线性变换改为:L’(B)=B⊕(B<<13) ⊕(B<<23),由于系统参数个固定参数是已知的,轮密钥即可求得。
- 加密解密过程
加密最后一轮变换时,输出为:
(Y0, Y1, Y2, Y3)=R(X32, X33, X34, X35)=(X35, X34, X33, X32)
最后输出是加密的反序,解密时只是将轮密钥的使用顺序进行逆向进行。
- SM4的应用
SM4在数据安全中的应用:
以固态硬盘为例,若用户数据的明文直接保存在存储介质上,那么只要拿到存储数据的存储介质,就能以一定的途径获取到其中存储的用户数据,比如换上其它的主控芯片、对存储介质上的电平进行分析等。我们可以在数据读写路径上加上一道门锁——SM4加解密:数据由主机传输到缓存RAM的过程中,使用SM4 算法加密,写入到缓存上的就是密文,并最终以密文的形式保存在存储介质Flash上;读取数据时再解密出明文返回给主机。
以上所述的加密过程对用户是完全透明的,用户完全感知不到加解密过程的存在。为确保明文数据只对授权用户可见,需要对加解密数据的密钥——介质密钥(MKey)进行保护,将其与授权用户关联起来。一种简单的关联方式如下图所示,一方面使用SM3算法对用户口令进行杂凑生成口令摘要,保存口令摘要用于身份鉴权;另一方面,对用户口令进行派生构造加密密钥(EKey),对介质密钥进行加密保存。
- 对比SM4与同类型算法
国际的DES算法和国产的SM4算法的目的都是为了加密保护静态储存和传输信道中的数据。从算法上看,国产SM4算法在计算过程中增加非线性变换,理论上能大大提高其算法的安全性,并且由专业机构进行了密码分析,民间也对21轮SM4进行了差分密码分析,安全性较高。
参考文献
[1] 国密算法在数据存储中的安全应用
[2] 国密标准文档