国密SM2加解密Demo
国密SM2加解密Demo
1、pom.xml
<!-- 国密 START--> <!-- <dependency>--> <!-- <groupId>org.bouncycastle</groupId>--> <!-- <artifactId>bcprov-jdk15to18</artifactId>--> <!-- <version>1.71</version>--> <!-- </dependency>--> <!-- 国密 END --> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.5.8</version> </dependency>
2、代码:
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 lombok.extern.slf4j.Slf4j; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import java.security.PrivateKey; import java.security.PublicKey; /** * 国密. * * @author lizhm */ @Slf4j public class Sm2Util { public static String PRIVATE_KEY = ""; public static String PUBLIC_KEY = ""; private static int PUBLIC_LENGTH = 130; /** * 生成公钥、私钥. * * @author lizhm * @date 2023/2/21 16:37 * @history <author> <time> <version> <desc> */ private static void 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); PRIVATE_KEY = HexUtil.encodeHexStr(privateKey); PUBLIC_KEY = HexUtil.encodeHexStr(publicKey); } /** * SM2加密算法. * * @param data 加密前的明文 * @param publicKey 公钥 * @return String 加密后的密文 * @author lizhm * @history <author> <time> <version> <desc> */ public static String encrypt(String publicKey, String data) { ECPublicKeyParameters ecPublicKeyParameters = null; //这里需要根据公钥的长度进行加工 if (publicKey.length() == PUBLIC_LENGTH) { //这里需要去掉开始第一个字节 第一个字节表示标记 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(data, KeyType.PublicKey); } /** * SM2加密算法. * * @param publicKey 公钥 * @param text 明文数据 * @return String * @author lizhm * @history <author> <time> <version> <desc> */ 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 cipherData 加密密文 * @param privateKey 私秘钥 * @return String 解密后的明文字符串 * @author lizhm * @history <author> <time> <version> <desc> */ public static String decrypt(String privateKey, String cipherData) { if (StrUtil.isBlank(cipherData)) { throw new RuntimeException("解密串为空,解密失败"); } 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 String * @author lizhm * @history <author> <time> <version> <desc> */ 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 String * @author lizhm * @history <author> <time> <version> <desc> */ public static String sign(String privateKey, String content) { ECPrivateKeyParameters ecPrivateKeyParameters = BCUtil.toSm2Params(privateKey); //创建sm2 对象 SM2 sm2 = new SM2(ecPrivateKeyParameters, null); return sm2.signHex(HexUtil.encodeHexStr(content)); } /** * 验证签名. * * @param publicKey 公钥 * @param content 待签名内容 * @param sign 签名值 * @return boolean * @author lizhm * @history <author> <time> <version> <desc> */ public static boolean verify(String publicKey, String content, String sign) { ECPublicKeyParameters ecPublicKeyParameters; //这里需要根据公钥的长度进行加工 if (publicKey.length() == PUBLIC_LENGTH) { //这里需要去掉开始第一个字节 第一个字节表示标记 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.verifyHex(HexUtil.encodeHexStr(content), sign); } }