SM2国密算法工具类
·
1、JAVA集成 SM2加密解密,及在线验证
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.69</version>
<scope>compile</scope>
</dependency>
2.工具类编写
import org.bouncycastle.asn1.gm.GMNamedCurves;
import org.bouncycastle.asn1.x9.X9ECParameters;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.engines.SM2Engine;
import org.bouncycastle.crypto.generators.ECKeyPairGenerator;
import org.bouncycastle.crypto.params.*;
import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.encoders.Hex;
import java.math.BigInteger;
import java.security.SecureRandom;
public class SM2Util {
private static final X9ECParameters SM2_EC_PARAMS = GMNamedCurves.getByName("sm2p256v1");
private static final ECDomainParameters DOMAIN_PARAMS = new ECDomainParameters(
SM2_EC_PARAMS.getCurve(),
SM2_EC_PARAMS.getG(),
SM2_EC_PARAMS.getN()
);
private static final String CHARSET = "UTF-8";
public static final int CIPHER_MODE_C1C2C3 = 0;
public static final int CIPHER_MODE_C1C3C2 = 1;
public static String encrypt(String plainText, String publicKeyHex, int cipherMode) throws Exception {
byte[] plainBytes = plainText.getBytes(CHARSET);
ECPoint publicKeyPoint = DOMAIN_PARAMS.getCurve().decodePoint(Hex.decode(publicKeyHex));
ECPublicKeyParameters publicKeyParams = new ECPublicKeyParameters(publicKeyPoint, DOMAIN_PARAMS);
SM2Engine sm2Engine = new SM2Engine();
sm2Engine.init(true, new ParametersWithRandom(publicKeyParams, new SecureRandom()));
byte[] c1c2c3Bytes = sm2Engine.processBlock(plainBytes, 0, plainBytes.length);
byte[] finalCipherBytes;
if (cipherMode == CIPHER_MODE_C1C3C2) {
finalCipherBytes = convertC1C2C3ToC1C3C2(c1c2c3Bytes);
} else {
finalCipherBytes = c1c2c3Bytes;
}
return Hex.toHexString(finalCipherBytes);
}
private static byte[] convertC1C2C3ToC1C3C2(byte[] c1c2c3) {
int c1Len = 65;
int c3Len = 32;
int c2Len = c1c2c3.length - c1Len - c3Len;
byte[] c1 = new byte[c1Len];
byte[] c2 = new byte[c2Len];
byte[] c3 = new byte[c3Len];
System.arraycopy(c1c2c3, 0, c1, 0, c1Len);
System.arraycopy(c1c2c3, c1Len, c2, 0, c2Len);
System.arraycopy(c1c2c3, c1Len + c2Len, c3, 0, c3Len);
byte[] c1c3c2 = new byte[c1c2c3.length];
System.arraycopy(c1, 0, c1c3c2, 0, c1Len);
System.arraycopy(c3, 0, c1c3c2, c1Len, c3Len);
System.arraycopy(c2, 0, c1c3c2, c1Len + c3Len, c2Len);
return c1c3c2;
}
public static String decrypt(String cipherTextHex, String privateKeyHex) throws Exception {
byte[] cipherBytes = Hex.decode(cipherTextHex);
byte[] c1c2c3Bytes;
int c1Len = 65;
int c3Len = 32;
if (cipherBytes.length > c1Len + c3Len) {
int c2Len = cipherBytes.length - c1Len - c3Len;
if (c2Len > 0) {
byte[] c1 = new byte[c1Len];
byte[] c3 = new byte[c3Len];
byte[] c2 = new byte[c2Len];
System.arraycopy(cipherBytes, 0, c1, 0, c1Len);
System.arraycopy(cipherBytes, c1Len, c3, 0, c3Len);
System.arraycopy(cipherBytes, c1Len + c3Len, c2, 0, c2Len);
c1c2c3Bytes = new byte[cipherBytes.length];
System.arraycopy(c1, 0, c1c2c3Bytes, 0, c1Len);
System.arraycopy(c2, 0, c1c2c3Bytes, c1Len, c2Len);
System.arraycopy(c3, 0, c1c2c3Bytes, c1Len + c2Len, c3Len);
} else {
c1c2c3Bytes = cipherBytes;
}
} else {
c1c2c3Bytes = cipherBytes;
}
BigInteger privateKeyD = new BigInteger(privateKeyHex, 16);
ECPrivateKeyParameters privateKeyParams = new ECPrivateKeyParameters(privateKeyD, DOMAIN_PARAMS);
SM2Engine sm2Engine = new SM2Engine();
sm2Engine.init(false, privateKeyParams);
byte[] decryptedBytes = sm2Engine.processBlock(c1c2c3Bytes, 0, c1c2c3Bytes.length);
return new String(decryptedBytes, CHARSET);
}
public static String decryptStandard(String cipherTextHex, String privateKeyHex) throws Exception {
return decrypt(cipherTextHex, privateKeyHex);
}
public static String decryptLegacy(String cipherTextHex, String privateKeyHex) throws Exception {
String base64Str = decrypt(cipherTextHex, privateKeyHex);
byte[] decodedBytes = java.util.Base64.getDecoder().decode(base64Str);
return new String(decodedBytes, CHARSET);
}
public static String[] generateKeys() throws Exception {
ECKeyPairGenerator generator = new ECKeyPairGenerator();
generator.init(new ECKeyGenerationParameters(DOMAIN_PARAMS, SecureRandom.getInstance("SHA1PRNG")));
AsymmetricCipherKeyPair keyPair = generator.generateKeyPair();
String privateKeyHex = ((ECPrivateKeyParameters) keyPair.getPrivate()).getD().toString(16);
ECPoint publicKeyPoint = ((ECPublicKeyParameters) keyPair.getPublic()).getQ();
String publicKeyHex = Hex.toHexString(publicKeyPoint.getEncoded(false));
return new String[]{publicKeyHex, privateKeyHex};
}
/**
* 测试方法:演示如何使用并验证与在线工具的兼容性
*/
public static void main(String[] args) throws Exception {
// ========== 第1步:生成全新的密钥对 ==========
String[] keys = generateKeys();
String publicKeyHex = keys[0];
String privateKeyHex = keys[1];
System.out.println("【全新生成】公钥: " + publicKeyHex);
System.out.println("【全新生成】私钥: " + privateKeyHex);
System.out.println("========================================");
// ========== 第2步:使用 C1C3C2 模式(国标)加密 ==========
String plainText = "Test测试123@#"; // 包含中文、英文、数字、符号的测试文本
int targetMode = CIPHER_MODE_C1C3C2; // 我们的目标是生成在线工具能解的格式
String cipherTextHex = encrypt(plainText, publicKeyHex, targetMode);
System.out.println("【加密结果 - C1C3C2模式】");
System.out.println("明文: " + plainText);
System.out.println("密文 (Hex): " + cipherTextHex);
System.out.println("密文长度: " + cipherTextHex.length() + " 个字符 (即 " + cipherTextHex.length()/2 + " 字节)");
System.out.println("========================================");
// ========== 第3步:使用本工具类本地解密(验证基础功能) ==========
try {
String decryptedText = decrypt(cipherTextHex, privateKeyHex);
System.out.println("【本地解密验证】");
System.out.println("结果: " + decryptedText);
System.out.println("与原明文一致吗? " + plainText.equals(decryptedText));
} catch (Exception e) {
System.out.println("【本地解密失败】错误: " + e.getMessage());
e.printStackTrace();
}
System.out.println("========================================");
System.out.println("私钥 (Private Key): " + privateKeyHex);
System.out.println("密文 (Ciphertext): " + cipherTextHex);
System.out.println("预期明文: " + plainText);
}
}
3.返回结果,代码解密解密成功!

4.网页测试,解密成功!

5.网站测试地址:
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)