JAVA国密SM234
https://cloud.tencent.com/developer/article/2421525
Hutool针对Bouncy Castle做了简化包装,用于实现国密算法中的SM2、SM3、SM4。
国密算法工具封装包括:
- 非对称加密和签名:SM2
- 摘要签名算法:SM3
- 对称加密:SM4
国密算法需要引入Bouncy Castle库的依赖。
MVN pom.xml配置文件增加依赖:
- 说明 bcprov-jdk15to18的版本请前往Maven中央库搜索,查找对应JDK的最新版本。
笔者采用以下2个JAR包(JAVA1.8)
Maven配置:
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15to18</artifactId>
<version>1.69</version>
</dependency>
SM3HMAC算法:
public static void main(String[] args) {
// String json = "appId=7f0d19a89e1558cb&data={}&encType=SM4&requestId=1&signType=SM3×tamp=1719017974&transType=PERSON&version=1.0.0&key=7f0d19a89e1558cb";
String json = "appId=7f0d19a89e1558cb&data={\"cardId\":\"\",\"certNo\":\"320723199210042814\",\"certType\":\"01\"}&encType=SM4&requestId=1&signType=SM3×tamp=1719215443112&transType=APP&version=1.0.0&key=7f0d19a89e1558cb";
String d = Sm3Utils.encryptKey("ALpyMppfcUJfN7ttrFvrPWMT0SV8rCvOorbAKVITtfPj",json);
System.out.println("@@@encryptKey:"+d);
}
import java.io.UnsupportedEncodingException;
import java.security.Security;
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.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;
public class Sm3Utils {
/**
* sm3算法加密(SM3HMAC)
*
* @param sm3Key 加密秘钥
* @param paramStr 待加密字符串
* @return 返回加密后,固定长度=32的16进制字符串
* @explain
*/
public static String encryptKey(String sm3Key, String paramStr) {
// 将返回的hash值转换成16进制字符串
String resultHexString = "";
try {
// 将字符串转换成byte数组
byte[] srcData = paramStr.getBytes(ENCODING);
// 调用hash()
byte[] strKey = sm3Key.getBytes();
byte[] resultHash = hmac(strKey, srcData);
// 将返回的hash值转换成16进制字符串
resultHexString = ByteUtils.toHexString(resultHash);
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
System.out.println("SM3秘钥{}"+sm3Key);// true
return resultHexString;
}
}
SM4加解密:
/**
* sm4加密
*
* @param chnlId 渠道id
* @param sm4key 渠道sm4密钥
* @param message 待加密报文
* @return 加密后的报文内容 String
* @throws Exception
*/
public static String sm4Encrypt(String chnlId, String sm4key, String message) throws Exception {
//用appId加密appSecret获取新秘钥
byte[] appSecretEncData = EasyGmUtils.sm4Encrypt(chnlId.substring(0, 16).getBytes("UTF-8"), sm4key.getBytes("UTF-8"));
byte[] secKey = Hex.toHexString(appSecretEncData).toUpperCase().substring(0, 16).getBytes("UTF-8");
System.out.println("NEWKEY:"+Hex.toHexString(appSecretEncData).toUpperCase());
System.out.println("NEWKEY-16:"+Hex.toHexString(appSecretEncData).toUpperCase().substring(0, 16));
//加密数据
String sEn = Hex.toHexString(EasyGmUtils.sm4Encrypt(secKey, message.getBytes("UTF-8"))).toUpperCase();
return sEn;
}
/**
* sm4解密
*
* @param chnlId 渠道id
* @param sm4key 渠道sm4密钥
* @param message 待解密报文
* @return 解密后的报文 String
* @throws Exception
*/
public static String sm4Decrypt(String chnlId, String sm4key, String message) throws Exception {
//生产解密key
byte[] appSecretEncDataDecode = EasyGmUtils.sm4Encrypt(chnlId.substring(0, 16).getBytes("UTF-8"), sm4key.getBytes("UTF-8"));
byte[] secKeyDecode = Hex.toHexString(appSecretEncDataDecode).toUpperCase().substring(0, 16).getBytes("UTF-8");
System.out.println("NEWKEY:"+Hex.toHexString(appSecretEncDataDecode).toUpperCase());
// return new String(EasyGmUtils.sm4Decrypt(secKeyDecode, message.getBytes("UTF-8")));
return new String(EasyGmUtils.sm4Decrypt(secKeyDecode, Hex.decode(message)), StandardCharsets.UTF_8);
}