JAVA國密SM234
https://cloud.tencent.com/developer/article/2421525
Hutool針對Bouncy Castle做了簡化包裝,用于實現(xiàn)國密算法中的SM2、SM3、SM4。
國密算法工具封裝包括:
- 非對稱加密和簽名:SM2
- 摘要簽名算法:SM3
- 對稱加密:SM4
國密算法需要引入Bouncy Castle庫的依賴。
MVN pom.xml配置文件增加依賴:
- 說明 bcprov-jdk15to18的版本請前往Maven中央庫搜索,查找對應(yīng)JDK的最新版本。
筆者采用以下2個JAR包(JAVA1.8)

image.png
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值轉(zhuǎn)換成16進制字符串
String resultHexString = "";
try {
// 將字符串轉(zhuǎn)換成byte數(shù)組
byte[] srcData = paramStr.getBytes(ENCODING);
// 調(diào)用hash()
byte[] strKey = sm3Key.getBytes();
byte[] resultHash = hmac(strKey, srcData);
// 將返回的hash值轉(zhuǎn)換成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 加密后的報文內(nèi)容 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));
//加密數(shù)據(jù)
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 {
//生產(chǎn)解密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);
}