首先引入maven
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15to18</artifactId> <version>1.69</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.4.1</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.10</version> </dependency>
直接上代码
import lombok.Data; /** * 1. @description: * 2. @author: xh * 3. @time: 2022/7/14 */ @Data public class SMKeyPair { //私钥 private String priKey; //公钥 private String pubKey; public SMKeyPair(String priKey, String pubKey) { this.priKey = priKey; this.pubKey = pubKey; } }
import cn.hutool.core.util.HexUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.BCUtil; import cn.hutool.crypto.SmUtil; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.SM2; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import java.security.PrivateKey; import java.security.PublicKey; /** * 1. @description: 国密SM2加解密 * 2. @author: xh * 3. @time: 2022/7/14 */ public class Sm2Utils { /** * 生成公私钥对(默认压缩公钥) * @return */ public static SMKeyPair genKeyPair() { SM2 sm2 = SmUtil.sm2(); //这里会自动生成对应的随机秘钥对 byte[] privateKey = BCUtil.encodeECPrivateKey(sm2.getPrivateKey()); //这里默认公钥压缩 公钥的第一个字节用于表示是否压缩 02或者03表示是压缩公钥,04表示未压缩公钥 byte[] publicKey = BCUtil.encodeECPublicKey(sm2.getPublicKey()); //这里得到未压缩的公钥 byte[] publicKey = ((BCECPublicKey) sm2.getPublicKey()).getQ().getEncoded(false); String priKey = HexUtil.encodeHexStr(privateKey); String pubKey = HexUtil.encodeHexStr(publicKey); return new SMKeyPair(priKey, pubKey); } /** * SM2加密算法 * @param publicKey 公钥 * @param text 数据 * @return */ public static String encrypt(String publicKey, String text) { ECPublicKeyParameters ecPublicKeyParameters = null; //这里需要根据公钥的长度进行加工 if (publicKey.length() == 130) { //这里需要去掉开始第一个字节 第一个字节表示标记 publicKey = publicKey.substring(2); String xhex = publicKey.substring(0, 64); String yhex = publicKey.substring(64, 128); ecPublicKeyParameters = BCUtil.toSm2Params(xhex, yhex); } else { PublicKey p = BCUtil.decodeECPoint(publicKey, SmUtil.SM2_CURVE_NAME); ecPublicKeyParameters = BCUtil.toParams(p); } //创建sm2 对象 SM2 sm2 = new SM2(null, ecPublicKeyParameters); // 公钥加密 return sm2.encryptBcd(text, KeyType.PublicKey); } /** * SM2加密算法 * @param publicKey 公钥 * @param text 明文数据 * @return */ public static String encrypt(PublicKey publicKey, String text) { ECPublicKeyParameters ecPublicKeyParameters = BCUtil.toParams(publicKey); //创建sm2 对象 SM2 sm2 = new SM2(null, ecPublicKeyParameters); // 公钥加密 return sm2.encryptBcd(text, KeyType.PublicKey); } /** * SM2解密算法 * @param privateKey 私钥 * @param cipherData 密文数据 * @return */ public static String decrypt(String privateKey, String cipherData) { ECPrivateKeyParameters ecPrivateKeyParameters = BCUtil.toSm2Params(privateKey); //创建sm2 对象 SM2 sm2 = new SM2(ecPrivateKeyParameters, null); // 私钥解密 return StrUtil.utf8Str(sm2.decryptFromBcd(cipherData, KeyType.PrivateKey)); } /** * SM2解密算法 * @param privateKey 私钥 * @param cipherData 密文数据 * @return */ public static String decrypt(PrivateKey privateKey, String cipherData) { ECPrivateKeyParameters ecPrivateKeyParameters = BCUtil.toParams(privateKey); //创建sm2 对象 SM2 sm2 = new SM2(ecPrivateKeyParameters, null); // 私钥解密 return StrUtil.utf8Str(sm2.decryptFromBcd(cipherData, KeyType.PrivateKey)); } /** * 私钥签名 * @param privateKey 私钥 * @param content 待签名内容 * @return */ public static String sign(String privateKey, String content) { ECPrivateKeyParameters ecPrivateKeyParameters = BCUtil.toSm2Params(privateKey); //创建sm2 对象 SM2 sm2 = new SM2(ecPrivateKeyParameters, null); String sign = sm2.signHex(HexUtil.encodeHexStr(content)); return sign; } /** * 验证签名 * @param publicKey 公钥 * @param content 待签名内容 * @param sign 签名值 * @return */ public static boolean verify(String publicKey, String content, String sign) { ECPublicKeyParameters ecPublicKeyParameters = null; //这里需要根据公钥的长度进行加工 if (publicKey.length() == 130) { //这里需要去掉开始第一个字节 第一个字节表示标记 publicKey = publicKey.substring(2); String xhex = publicKey.substring(0, 64); String yhex = publicKey.substring(64, 128); ecPublicKeyParameters = BCUtil.toSm2Params(xhex, yhex); } else { PublicKey p = BCUtil.decodeECPoint(publicKey, SmUtil.SM2_CURVE_NAME); ecPublicKeyParameters = BCUtil.toParams(p); } //创建sm2 对象 SM2 sm2 = new SM2(null, ecPublicKeyParameters); boolean verify = sm2.verifyHex(HexUtil.encodeHexStr(content), sign); return verify; } public static void main(String[] args) { SMKeyPair smKeyPair = genKeyPair(); String priKey = smKeyPair.getPriKey(); System.out.println("私钥"+ priKey); String pubKey = smKeyPair.getPubKey(); System.out.println("公钥"+ pubKey); //明文 String text = "123123123"; System.out.println("测试明文文本" + text); //签名测试 String sign = sign(priKey, text); System.out.println("生成签名" + sign); //验签测试 boolean verify = verify(pubKey, text, sign); System.out.println("验签结果" + verify); //加解密测试 String encryptData = encrypt(pubKey, text); System.out.println("加密结果" + encryptData); String decryptData = decrypt(priKey, encryptData); System.out.println("解密结果" + decryptData); } }
私钥d1197a8dc58791f3d62c28a3447089f98fb9cf46f4a0608b6db9f119b939c16f 公钥035a5f4a04c818e9721ca88783c49ee391e3c4b42422fd7ac83a1abdb6ca5dd546 测试明文文本123123123 生成签名3045022100c87cf39c28e353937540acf14d87451722289098de6fb8ac0e1a33d7082a7daf022031786170b1bde6fbc86f10e3c0a32b428baf5071c18c5c2b1f378ab4fab440c6 验签结果true 加密结果04782AA43A09A3716819B7DE201B962EBE7A48A3471B1963DDAFB723EC20A4F20BECB12201A3A6477E226130E5DB9BF786C9EBA5BC82912D7AE240025318140649F9B364ECC6F61412C561556768D9C2BC7B9CDE264F4B62153711F0991EECAA405982BE5AE2F6D2C3E2 解密结果123123123