Java代码SM2算法加解密、签名验签的实现Demo:
package com.example.demo; import org.bouncycastle.asn1.gm.GMNamedCurves; import org.bouncycastle.asn1.x9.X9ECParameters; import org.bouncycastle.crypto.AsymmetricCipherKeyPair; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.engines.SM2Engine; import org.bouncycastle.crypto.generators.ECKeyPairGenerator; import org.bouncycastle.crypto.params.*; import org.bouncycastle.crypto.signers.SM2Signer; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.util.encoders.Hex; import java.math.BigInteger; import java.security.SecureRandom; import java.security.Security; public final class SM2Demo { static { Security.addProvider(new BouncyCastleProvider()); } /* ---------- 密钥对 ---------- */ public static AsymmetricCipherKeyPair genKeyPair() { X9ECParameters sm2 = GMNamedCurves.getByName("sm2p256v1"); ECDomainParameters domain = new ECDomainParameters(sm2.getCurve(), sm2.getG(), sm2.getN()); ECKeyPairGenerator gen = new ECKeyPairGenerator(); gen.init(new ECKeyGenerationParameters(domain, new SecureRandom())); return gen.generateKeyPair(); } /* ---------- 加密 ---------- */ public static String encrypt(String hexPubKey, String plain) throws Exception { X9ECParameters sm2 = GMNamedCurves.getByName("sm2p256v1"); ECDomainParameters domain = new ECDomainParameters(sm2.getCurve(), sm2.getG(), sm2.getN()); ECPoint pubPoint = sm2.getCurve().decodePoint(Hex.decode(hexPubKey)); ECPublicKeyParameters pubKey = new ECPublicKeyParameters(pubPoint, domain); SM2Engine engine = new SM2Engine(); engine.init(true, new ParametersWithRandom(pubKey, new SecureRandom())); byte[] cipher = engine.processBlock(plain.getBytes(), 0, plain.getBytes().length); return Hex.toHexString(cipher); } /* ---------- 解密 ---------- */ public static String decrypt(String hexPriKey, String hexCipher) throws Exception { X9ECParameters sm2 = GMNamedCurves.getByName("sm2p256v1"); ECDomainParameters domain = new ECDomainParameters(sm2.getCurve(), sm2.getG(), sm2.getN()); BigInteger d = new BigInteger(hexPriKey, 16); ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(d, domain); SM2Engine engine = new SM2Engine(); engine.init(false, priKey); byte[] plain = engine.processBlock(Hex.decode(hexCipher), 0, Hex.decode(hexCipher).length); return new String(plain); } /* ---------- 签名 ---------- */ public static String sign(String hexPriKey, String id, String plain) throws Exception { X9ECParameters sm2 = GMNamedCurves.getByName("sm2p256v1"); ECDomainParameters domain = new ECDomainParameters(sm2.getCurve(), sm2.getG(), sm2.getN()); BigInteger d = new BigInteger(hexPriKey, 16); ECPrivateKeyParameters priKey = new ECPrivateKeyParameters(d, domain); SM2Signer signer = new SM2Signer(); CipherParameters param = new ParametersWithID(priKey, id.getBytes()); signer.init(true, param); signer.update(plain.getBytes(), 0, plain.getBytes().length); byte[] sig = signer.generateSignature(); return Hex.toHexString(sig); } /* ---------- 验签 ---------- */ public static boolean verify(String hexPubKey, String id, String plain, String hexSig) throws Exception { X9ECParameters sm2 = GMNamedCurves.getByName("sm2p256v1"); ECDomainParameters domain = new ECDomainParameters(sm2.getCurve(), sm2.getG(), sm2.getN()); ECPoint pubPoint = sm2.getCurve().decodePoint(Hex.decode(hexPubKey)); ECPublicKeyParameters pubKey = new ECPublicKeyParameters(pubPoint, domain); SM2Signer signer = new SM2Signer(); CipherParameters param = new ParametersWithID(pubKey, id.getBytes()); signer.init(false, param); signer.update(plain.getBytes(), 0, plain.getBytes().length); return signer.verifySignature(Hex.decode(hexSig)); } /* ---------- 演示 ---------- */ public static void main(String[] args) throws Exception { AsymmetricCipherKeyPair kp = genKeyPair(); String pubHex = Hex.toHexString(((ECPublicKeyParameters) kp.getPublic()).getQ().getEncoded(false)); String priHex = ((ECPrivateKeyParameters) kp.getPrivate()).getD().toString(16); System.out.println("公钥: " + pubHex); System.out.println("私钥: " + priHex); String plain = "hello 国密 SM2"; System.out.println("原始数:" + plain); String cipher = encrypt(pubHex, plain); System.out.println("加密后: " + cipher); String recovered = decrypt(priHex, cipher); System.out.println("解密后: " + recovered); String id = "1234567812345678"; // 国密标准推荐 16 字节 ID String sig = sign(priHex, id, plain); System.out.println("签名 : " + sig); boolean ok = verify(pubHex, id, plain, sig); System.out.println("验签结果: " + ok); } }
pom依赖引入 :
<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.70</version> <!-- 版本号可根据需要更新,1.70及以上版本对SM2支持完善 --> </dependency>
浙公网安备 33010602011771号