Java国密加密SM3代码
前言
提示:使用国密算法的意义:
随着金融安全上升到国家安全高度,近年来国家有关机关和监管机构站在国家安全和长远战略的高度提出了推动国密算法应用实施、加强行业安全可控的要求。摆脱对国外技术和产品的过度依赖,建设行业网络安全环境,增强我国行业信息系统的“安全可控”能力显得尤为必要和迫切。
提示:以下是本篇文章正文内容,下面案例可供参考
一、SM3是什么?
SM3杂凑算法(vs SHA-256)
SM3密码杂凑(哈希、散列)算法给出了杂凑函数算法的计算方法和计算步骤,并给出了运算示例。此算法适用于商用密码应用中的数字签名和验证,消息认证码的生成与验证以及随机数的生成,可满足多种密码应用的安全需求。在SM2,SM9标准中使用。
此算法对输入长度小于2的64次方的比特消息,经过填充和迭代压缩,生成长度为256比特的杂凑值,其中使用了异或,模,模加,移位,与,或,非运算,由填充,迭代过程,消息扩展和压缩函数所构成。具体算法及运算示例见SM3标准。
2005年,Wang等人给出了MD5算法和SHA-1算法的碰撞攻击方法,现今被广泛应用的MD5算法和SHA-1算法不再是安全的算法。
SM3密码摘要算法是中国国家密码管理局2010年公布的中国商用密码杂凑算法标准。SM3算法适用于商用密码应用中的数字签名和验证,是在SHA-256基础上改进实现的一种算法。SM3算法采用Merkle-Damgard结构,消息分组长度为512位,摘要值长度为256位。
SM3算法的压缩函数与SHA-256的压缩函数具有相似的结构,但是SM3算法的设计更加复杂,比如压缩函数的每一轮都使用2个消息字。
现今为止,SM3算法的安全性相对较高。
SM3主要用于数字签名及验证、消息认证码生成及验证、随机数生成等,其算法公开。据国家密码管理局表示,其安全性及效率与SHA-256相当。
二、使用步骤
1.引入库
代码如下(示例):
<!--国密--><dependency><groupId>org.bouncycastle</groupId><artifactId>bcprov-jdk15on</artifactId><version>1.56</version></dependency>
2.SM3工具类
代码如下(示例):
/**
* @author SongWei
* @version 1.0.0
* @ClassName spring-cloud.com.boot.cloud.sm.Sm3Tool.java
* @Description TODO
* @createTime 2018年10月28日 14:29:00
*/publicclassSm3Tool{publicstaticfinalbyte[] iv={0x73,(byte)0x80,0x16,0x6f,0x49,0x14,(byte)0xb2,(byte)0xb9,0x17,0x24,0x42,(byte)0xd7,(byte)0xda,(byte)0x8a,0x06,0x00,(byte)0xa9,0x6f,0x30,(byte)0xbc,(byte)0x16,0x31,0x38,(byte)0xaa,(byte)0xe3,(byte)0x8d,(byte)0xee,0x4d,(byte)0xb0,(byte)0xfb,0x0e,0x4e};publicstaticint[]Tj=newint[64];static{for(int i=0; i<16; i++){Tj[i]=0x79cc4519;}for(int i=16; i<64; i++){Tj[i]=0x7a879d8a;}}publicstaticbyte[]CF(byte[]V,byte[]B){int[] v, b;
v=convert(V);
b=convert(B);returnconvert(CF(v, b));}privatestaticint[]convert(byte[] arr){int[] out=newint[arr.length/4];byte[] tmp=newbyte[4];for(int i=0; i< arr.length; i+=4){System.arraycopy(arr, i, tmp,0,4);
out[i/4]=bigEndianByteToInt(tmp);}return out;}privatestaticbyte[]convert(int[] arr){byte[] out=newbyte[arr.length*4];byte[] tmp=null;for(int i=0; i< arr.length; i++){
tmp=bigEndianIntToByte(arr[i]);System.arraycopy(tmp,0, out, i*4,4);}return out;}publicstaticint[]CF(int[]V,int[]B){int a, b, c, d, e, f, g, h;int ss1, ss2, tt1, tt2;
a=V[0];
b=V[1];
c=V[2];
d=V[3];
e=V[4];
f=V[5];
g=V[6];
h=V[7];int[][] arr=expand(B);int[] w= arr[0];int[] w1= arr[1];for(int j=0; j<64; j++){
ss1=(bitCycleLeft(a,12)+ e+bitCycleLeft(Tj[j], j));
ss1=bitCycleLeft(ss1,7);
ss2= ss1^bitCycleLeft(a,12);
tt1=FFj(a, b, c, j)+ d+ ss2+ w1[j];
tt2=GGj(e, f, g, j)+ h+ ss1+ w[j];
d= c;
c=bitCycleLeft(b,9);
b= a;
a= tt1;
h= g;
g=bitCycleLeft(f,19);
f= e;
e=P0(tt2);/*System.out.print(j+" ");
System.out.print(Integer.toHexString(a)+" ");
System.out.print(Integer.toHexString(b)+" ");
System.out.print(Integer.toHexString(c)+" ");
System.out.print(Integer.toHexString(d)+" ");
System.out.print(Integer.toHexString(e)+" ");
System.out.print(Integer.toHexString(f)+" ");
System.out.print(Integer.toHexString(g)+" ");
System.out.print(Integer.toHexString(h)+" ");
System.out.println("");*/}// System.out.println("");int[] out=newint[8];
out[0]= a^V[0];
out[1]= b^V[1];
out[2]= c^V[2];
out[3]= d^V[3];
out[4]= e^V[4];
out[5]= f^V[5];
out[6]= g^V[6];
out[7]= h^V[7];return out;}privatestaticint[][]expand(int[]B){intW[]=newint[68];int W1[]=newint[64];for(int i=0; i<B.length; i++){W[i]=B[i];}for(int i=16; i<68; i++){W[i]=P1(W[i-16]^W[i-9]^bitCycleLeft(W[i-3],15))^bitCycleLeft(W[i-13],7)^W[i-6];}for(int i=0; i<64; i++){
W1[i]=W[i]^W[i+4];}int arr[][]=newint[][]{W, W1};return arr;}privatestaticbyte[]bigEndianIntToByte(int num){returnback(SecurityUtils.intToBytes(num));}privatestaticintbigEndianByteToInt(byte[] bytes){returnSecurityUtils.byteToInt(back(bytes));}privatestaticintFFj(intX,intY,intZ,int j){if(j>=0&& j<=15){returnFF1j(X,Y,Z);}else{returnFF2j(X,Y,Z);}}privatestaticintGGj(intX,intY,intZ,int j){if(j>=0&& j<=15){returnGG1j(X,Y,Z);}else{returnGG2j(X,Y,Z);}}// 逻辑位运算函数privatestaticintFF1j(intX,intY,intZ){int tmp=X^Y^Z;return tmp;}privatestaticintFF2j(intX,intY,intZ){int tmp=((X&Y)|(X&Z)|(Y&Z));return tmp;}privatestaticintGG1j(intX,intY,intZ){int tmp=X^Y^Z;return tmp;}privatestaticintGG2j(intX,intY,intZ){int tmp=(X&Y)|(~X&Z);return tmp;}privatestaticintP0(intX){int y=rotateLeft(X,9);
y=bitCycleLeft(X,9);int z=rotateLeft(X,17);
z=bitCycleLeft(X,17);int t=X^ y^ z;return t;}privatestaticintP1(intX){int t=X^bitCycleLeft(X,15)^bitCycleLeft(X,23);return t;}/**
* 对最后一个分组字节数据padding
*
* @param in
* @param bLen 分组个数
* @return
*/publicstaticbyte[]padding(byte[] in,int bLen){int k=448-(8* in.length+1)%512;if(k<0){
k=960-(8* in.length+1)%512;}
k+=1;byte[] padd=newbyte[k/8];
padd[0]=(byte)0x80;long n= in.length*8+ bLen*512;byte[] out=newbyte[in.length+ k/8+64/8];int pos=0;System.arraycopy(in,0, out,0, in.length);
pos+= in.length;System.arraycopy(padd,0, out, pos, padd.length);
pos+= padd.length;byte[] tmp=back(SecurityUtils.longToBytes(n));System.arraycopy(tmp,0, out, pos, tmp.length);return out;}/**
* 字节数组逆序
*
* @param in
* @return
*/privatestaticbyte[]back(byte[] in){byte[] out=newbyte[in.length];for(int i=0; i< out.length; i++){
out[i]= in[out.length- i-1];}return out;}publicstaticintrotateLeft(int x,int n){return(x<< n)|(x>>(32- n));}privatestaticintbitCycleLeft(int n,int bitLen){
bitLen%=32;byte[] tmp=bigEndianIntToByte(n);int byteLen= bitLen