package com.nanjing.water.common.util; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.params.ParametersWithRandom; import org.bouncycastle.crypto.signers.SM2Signer; import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.springframework.util.Base64Utils; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.security.*; import java.security.spec.*; public class SM2Util { /** * 要生成的EC域参数的标准名称 */ private static final String STANDARD_NAME = "sm2p256v1"; /** * 算法 */ private static final String ALGORITHM = "EC"; /** * 字符编码 */ private static final Charset CHARSET = StandardCharsets.UTF_8; /** * 生成密钥对 * * @return 密钥对 */ private static KeyPair generateSm2KeyPair() throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { //使用标准名称创建EC参数生成的参数规范 final ECGenParameterSpec sm2Spec = new ECGenParameterSpec(STANDARD_NAME); // 获取一个椭圆曲线类型的密钥对生成器 final KeyPairGenerator kpg = KeyPairGenerator.getInstance(ALGORITHM, new BouncyCastleProvider()); kpg.initialize(sm2Spec, new SecureRandom()); // 通过密钥生成器生成密钥对 return kpg.generateKeyPair(); } /** * 生成密钥对 * * @return 密钥对 */ public static String[] genKeyPair() throws InvalidAlgorithmParameterException, NoSuchAlgorithmException { KeyPair keyPair = generateSm2KeyPair(); PrivateKey privateKey = keyPair.getPrivate(); PublicKey publicKey = keyPair.getPublic(); return new String[]{ Base64Utils.encodeToString(privateKey.getEncoded()), Base64Utils.encodeToString(publicKey.getEncoded()) }; } /** * 私钥转换为 {@link ECPrivateKeyParameters} * * @param key 私钥 * @return 私钥{@link ECPrivateKeyParameters} */ private static ECPrivateKeyParameters privateKeyToParams(byte[] key) throws InvalidKeyException, InvalidKeySpecException, NoSuchAlgorithmException { KeySpec keySpec = new PKCS8EncodedKeySpec(key); PrivateKey privateKey = getKeyFactory().generatePrivate(keySpec); ; return (ECPrivateKeyParameters) ECUtil.generatePrivateKeyParameter(privateKey); } /** * 公钥转换为 {@link ECPublicKeyParameters} * * @param key 公钥 * @return 公钥{@link ECPublicKeyParameters} */ private static ECPublicKeyParameters publicKeyToParams(byte[] key) throws InvalidKeyException, InvalidKeySpecException, NoSuchAlgorithmException { KeySpec keySpec = new X509EncodedKeySpec(key); PublicKey publicKey = getKeyFactory().generatePublic(keySpec); return (ECPublicKeyParameters) ECUtil.generatePublicKeyParameter(publicKey); } /** * 获取{@link KeyFactory} * * @return {@link KeyFactory} */ private static KeyFactory getKeyFactory() throws NoSuchAlgorithmException { final Provider provider = new BouncyCastleProvider(); return KeyFactory.getInstance(ALGORITHM, provider); } /** * 签名 * * @param content 原始串 * @param priKey 私钥 * @return 签名 */ public static String sign(String content, String priKey) throws Exception { byte[] data = content.getBytes(CHARSET); byte[] privateKey = Base64Utils.decode(priKey.getBytes(CHARSET)); SM2Signer signer = new SM2Signer(); CipherParameters param = new ParametersWithRandom(privateKeyToParams(privateKey)); signer.init(true, param); signer.update(data, 0, data.length); byte[] buffer = signer.generateSignature(); return Base64Utils.encodeToString(buffer); } /** * 用公钥检验数字签名的合法性 * * @param content 原始串 * @param sign 待验证签名 * @param publicKey 私钥 * @return 是否验证通过 */ public static boolean verify(String content, String sign, String publicKey) throws Exception { byte[] data = content.getBytes(CHARSET); byte[] signBuffer = Base64Utils.decodeFromString(sign); byte[] keyBuffer = Base64Utils.decodeFromString(publicKey); SM2Signer signer = new SM2Signer(); CipherParameters param = publicKeyToParams(keyBuffer); signer.init(false, param); signer.update(data, 0, data.length); return signer.verifySignature(signBuffer); } // public static void main(String[] args) { // Security.addProvider(new BouncyCastleProvider()); // // try { // // 生成密钥对 // String[] keyPair = SM2Util.genKeyPair(); // String privateKey = keyPair[0]; // String publicKey = keyPair[1]; // // // 对消息进行签名 // String message = "你好,世界!"; // String signature = SM2Util.sign(message, privateKey); // System.out.println("生成的签名: " + signature); // // // 验证签名 // boolean isValid = SM2Util.verify(message, signature, publicKey); // System.out.println("签名验证结果: " + isValid); // } catch (Exception e) { // e.printStackTrace(); // } // } }