1 算法简介
SM3算法也是一种哈希算法,中国国家密码管理局在2010年发布,其名称是SM3密码杂凑算法,密码管理局有该算法的详细说明,可以到其网站下载《GBT 32905-2016 信息安全技术 SM3密码杂凑算法》和《GMT 0004-2012 SM3密码杂凑算法》。
算法的本质给任意长度的数据(l≤2^64)经过填充、迭代压缩后,生成固定长度的杂凑值,这个固定长度就是256比特
2 处理过程
- 第一步:填充。使填充后的数据的长度是512的整数倍。在数据的末尾上加一个1;然后把原始数据的长度用64比特表示,放在最后面;再看看现在的数据的长度值离512的整数还差多少个,差多少个就填多少个0在加的这个1和64比特的长度之间。
- 第二步:分组。把填充后的信息按照512比特一个分组进行分组。如果分成了n组,就是B0,B1,…,Bn−1个分组。
-
第三步:迭代压缩。对每一个分组都进行消息扩展,再借助寄存器得到最后的杂凑值(哈希值)。迭代压缩这里有很多中间变量和寄存器的操作,具体还是看一下算法。

3 优缺点
- 优点:
安全性高,虽然说安全性和SHA256相当。但个人认为应该指理论上与SHA256相当,毕竟都是哈希算法以及256位摘要。但实际应该比SHA256更高,毕竟破解不可逆算法就是靠字典库,而SHA256的字典库远大于SM3。
- 缺点:
大数据量下加密速度慢。
4 java实现:
基于BouncyCastle库实现:
package org.liuy.pki;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Arrays;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.util.encoders.Hex;
import com.sun.org.apache.xml.internal.security.utils.Base64;
/**
*
* 国密SM3工具包
*
* @author liuy
*
*/
public class SM3Tools {
/**
* SM3加密方式之:不提供密钥的方式 SM3加密,返回加密后长度为64位的16进制字符串
*
* @param src 明文
* @return 加密字节组
*/
public static byte[] encrypt(byte[] srcByte) {
SM3Digest sm3 = new SM3Digest();
sm3.update(srcByte, 0, srcByte.length);
byte[] encryptByte = new byte[sm3.getDigestSize()];
sm3.doFinal(encryptByte, 0);
return encryptByte;
}
/**
* 计算文件sm3值
* @param file
* @return sm3Hex
*/
public static String encryptFile(File file) throws FileNotFoundException {
try {
BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
SM3Digest sm3 = new SM3Digest();
int bufferSize = 16384;
byte [] buffer = new byte[bufferSize];
int sizeRead = -1;
while ((sizeRead = in.read(buffer)) != -1) {
sm3.update(buffer, 0, buffer.length);
}
in.close();
byte[] encryptByte = new byte[sm3.getDigestSize()];
sm3.doFinal(encryptByte, 0);
return Hex.toHexString(encryptByte);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* SM3散列
*
* @param data 数据明文
* @return 加密后长度为64位的16进制字符串
*/
public static String encrypt(String data) {
byte[] sm3Arry= encrypt(data.getBytes());
return Hex.toHexString(sm3Arry);
}
/**
* hmacSM3加密: 返回Base64 hmac值
*
* @param srcB64 Base64数据
* @param keyB64 Base64密钥
* @return
* @throws Exception
*/
public static String hmacSM3(String srcB64, String keyB64) throws Exception {
byte[] srcByte = Base64.decode(srcB64);
byte[] keyByte = Base64.decode(keyB64);
byte[] sm3Hmac=hmacSM3(srcByte,keyByte);
return Base64.encode(sm3Hmac);
}
/**
* 计算hmac-sm3值
* @param srcByte
* @param keyByte
* @return
*/
public static byte[] hmacSM3(byte[] srcByte,byte[] keyByte) {
KeyParameter keyParameter = new KeyParameter(keyByte);
SM3Digest sm3 = new SM3Digest();
HMac hMac = new HMac(sm3);
hMac.init(keyParameter);
hMac.update(srcByte, 0, srcByte.length);
byte[] result = new byte[hMac.getMacSize()];
hMac.doFinal(result, 0);
return result;
}
/**
* 利用源数据+密钥校验与密文是否一致
*
* @param src 源数据
* @param key 任意长度密钥
* @param sm3HexStr 密文
* @return
* @throws Exception
*/
public static boolean VerifyHMac(byte[] srcArry, byte[] keyArry, byte[] hmacArry) throws Exception {
byte[] newHmac = hmacSM3(srcArry, keyArry);
return Arrays.equals(newHmac,hmacArry);
}
/**
* 校验源数据与加密数据是否一致
*
* @param src 源数据
* @param sm3HexStr 16进制的加密数据
* @return
* @throws Exception
*/
public static boolean verify(byte[] srcByte, String sm3HexStr) throws Exception {
byte[] newHashCode = encrypt(srcByte);
String newHashCodeHex=Hex.toHexString(newHashCode);
if(newHashCodeHex.endsWith(sm3HexStr))
{
return true;
}
else
{
return false;
}
}
}
完整代码见:国密演示: SM算法用法,页面的SM3功能菜单:

9439

被折叠的 条评论
为什么被折叠?



