在商用密码体系中,SM3主要用于数字签名及验证、消息认证码生成及验证、随机数生成等,其算法公开。据国家密码管理局表示,其安全性及效率与SHA-256相当。
需要引入如下坐标依赖:
代码语言:javascript复制<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.68</version>
</dependency>
自定义密钥加密及校验
加密
代码语言:javascript复制 private static final String ENCODING = "UTF-8";
/**
* 加密
*
* @param src 明文
* @param key 密钥
* @return
* @throws Exception
*/
public static String encrypt(String src, String key) throws Exception {
return ByteUtils.toHexString(getEncryptByKey(src, key));
}
/**
* SM3加密方式之: 根据自定义密钥进行加密,返回加密后长度为32位的16进制字符串
*
* @param src 源数据
* @param key 密钥
* @return
* @throws Exception
*/
public static byte[] getEncryptByKey(String src, String key) throws Exception {
byte[] srcByte = src.getBytes(ENCODING);
byte[] keyByte = key.getBytes(ENCODING);
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;
}
校验
代码语言:javascript复制 /**
* 利用源数据 密钥校验与密文是否一致
*
* @param src 源数据
* @param key 密钥
* @param sm3HexStr 密文
* @return
* @throws Exception
*/
public static boolean verify(String src, String key, String sm3HexStr) throws Exception {
byte[] sm3HashCode = ByteUtils.fromHexString(sm3HexStr);
byte[] newHashCode = getEncryptByKey(src, key);
return Arrays.equals(newHashCode, sm3HashCode);
}
无密钥的加密及校验
加密
代码语言:javascript复制 /**
* SM3加密方式之:不提供密钥的方式 SM3加密,返回加密后长度为64位的16进制字符串
*
* @param src 明文
* @return
*/
public static String encrypt(String src) {
return ByteUtils.toHexString(getEncryptBySrcByte(src.getBytes()));
}
/**
* 返回长度为32位的加密后的byte数组
*
* @param srcByte
* @return
*/
public static byte[] getEncryptBySrcByte(byte[] srcByte) {
SM3Digest sm3 = new SM3Digest();
sm3.update(srcByte, 0, srcByte.length);
byte[] encryptByte = new byte[sm3.getDigestSize()];
sm3.doFinal(encryptByte, 0);
return encryptByte;
}
校验
代码语言:javascript复制 /**
* 校验源数据与加密数据是否一致
*
* @param src 源数据
* @param sm3HexStr 16进制的加密数据
* @return
* @throws Exception
*/
public static boolean verify(String src, String sm3HexStr) throws Exception {
byte[] sm3HashCode = ByteUtils.fromHexString(sm3HexStr);
byte[] newHashCode = getEncryptBySrcByte(src.getBytes(ENCODING));
return Arrays.equals(newHashCode, sm3HashCode);
}
测试验证
代码语言:javascript复制public static void main(String[] args) throws Exception {
String srcStr = "今天天气很晴朗";
String key = "zjqzjq";
// ******************************自定义密钥加密及校验*****************************************
String hexStrByKey = SM3Utils.encrypt(srcStr, key);
System.out.println("带密钥加密后的密文:" hexStrByKey);
System.out.println("明文(带密钥)与密文校验结果:" SM3Utils.verify(srcStr, key, hexStrByKey));
// ******************************无密钥的加密及校验******************************************
String hexStrNoKey = SM3Utils.encrypt(srcStr);
System.out.println("不带密钥加密后的密文:" hexStrNoKey);
System.out.println("明文(不带密钥)与密文校验结果:" SM3Utils.verify(srcStr, hexStrNoKey));
}
结果输出如下: