rsa加密算法与 国密SM2 加密算法
rsa 算法工具类:RsaKit
private static final Logger LOGGER = LoggerFactory.getLogger(RsaKit.class); public static final String KEY_ALGORITHM = "RSA"; public static final String KEY_ALGORITHM_PADDING = "RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING"; public static final String SIGNATURE_ALGORITHM = "SHA256withRSA";public RsaKit() { }public static ByteString encrypt(byte[] content, int offset, int length, PublicKey publicKey) {try {OAEPParameterSpec oaepParameterSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSpecified.DEFAULT);Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");cipher.init(1, publicKey, oaepParameterSpec);return ByteString.of(cipher.doFinal(content, offset, length));} catch (Exception var6) {LOGGER.error("rsa encrypt error, publicKey={}, data={}", new Object[]{publicKey, Arrays.toString(content), var6});throw new ApiException("rsa encrypt ex", var6);} }public static ByteString decrypt(byte[] content, int offset, int length, PrivateKey privateKey) {try {OAEPParameterSpec oaepParameterSpec = new OAEPParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, PSpecified.DEFAULT);Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWITHSHA-256ANDMGF1PADDING");cipher.init(2, privateKey, oaepParameterSpec);return ByteString.of(cipher.doFinal(content, offset, length));} catch (Exception var6) {LOGGER.error("rsa decrypt error, privateKey={}, data={}", new Object[]{privateKey, Arrays.toString(content), var6});throw new ApiException("rsa decrypt ex", var6);} }public static ByteString encrypt(String publicKey, byte[] content) {return encrypt(content, 0, content.length, decodePublicKey(publicKey)); }public static ByteString decrypt(String privateKey, byte[] content) {return decrypt(content, 0, content.length, decodePrivateKey(privateKey)); }public static Pair<RSAPublicKey, RSAPrivateKey> genKeyPair(int rsaKeySize) {try {KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");keyPairGen.initialize(rsaKeySize);KeyPair keyPair = keyPairGen.generateKeyPair();RSAPublicKey publicKey = (RSAPublicKey)keyPair.getPublic();RSAPrivateKey privateKey = (RSAPrivateKey)keyPair.getPrivate();return Pair.of(publicKey, privateKey);} catch (NoSuchAlgorithmException var5) {throw new ApiException("generate rsa kay pair error", var5);} }public static Pair<String, String> genKeyPairs(int rsaKeySize) {Pair<RSAPublicKey, RSAPrivateKey> keyPair = genKeyPair(rsaKeySize);return Pair.of(encodeBase64((Key)keyPair.getRight()), encodeBase64((Key)keyPair.getLeft())); }public static RSAPublicKey decodePublicKey(String key) {byte[] keyBytes = Base64.getMimeDecoder().decode(key);X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);try {KeyFactory keyFactory = KeyFactory.getInstance("RSA");return (RSAPublicKey)keyFactory.generatePublic(keySpec);} catch (Exception var4) {throw new ApiException("rsa getPublicKey ex", var4);} }public static RSAPrivateKey decodePrivateKey(String privateKey) {byte[] keyBytes = Base64.getMimeDecoder().decode(privateKey);PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);try {KeyFactory keyFactory = KeyFactory.getInstance("RSA");return (RSAPrivateKey)keyFactory.generatePrivate(keySpec);} catch (Exception var4) {throw new ApiException("rsa getPrivateKey ex", var4);} }public static String encodeBase64(Key key) {return Base64.getEncoder().encodeToString(key.getEncoded()); }public static ByteString sign(byte[] data, String privateKey) throws Exception {Signature signature = Signature.getInstance("SHA256withRSA");signature.initSign(decodePrivateKey(privateKey));signature.update(data);return ByteString.of(signature.sign()); }public static boolean verify(byte[] data, String publicKey, byte[] sign) throws Exception {Signature signature = Signature.getInstance("SHA256withRSA");signature.initVerify(decodePublicKey(publicKey));signature.update(data);return signature.verify(sign); }
sm2算法工具类:SM2Kit
public SM2Kit() { }public static ECPrivateKeyParameters decodePriKeyParams(String key) {return ECKeyUtil.decodePrivateKeyParams(Base64.getDecoder().decode(key)); }public static ECPublicKeyParameters decodePubKeyParams(String key) {return ECKeyUtil.decodePublicKeyParams(Base64.getDecoder().decode(key)); }public static String encodePriKeyParams(ECPrivateKeyParameters key) {return Base64.getEncoder().encodeToString(key.getD().toByteArray()); }public static String encodePubKeyParams(ECPublicKeyParameters key) {return Base64.getEncoder().encodeToString(key.getQ().getEncoded(false)); }public static Pair<String, String> genKeyPairs() {ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");KeyPair keyPair = KeyUtil.generateKeyPair("ECIES", 256, new SecureRandom(), new AlgorithmParameterSpec[]{sm2Spec});String pri = Base64.getEncoder().encodeToString(keyPair.getPrivate().getEncoded());String pub = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());return Pair.of(pri, pub); }public static Pair<ECPrivateKeyParameters, ECPublicKeyParameters> genKeyPair() {ECGenParameterSpec sm2Spec = new ECGenParameterSpec("sm2p256v1");KeyPair keyPair = KeyUtil.generateKeyPair("ECIES", 256, new SecureRandom(), new AlgorithmParameterSpec[]{sm2Spec});PrivateKey privateKey = keyPair.getPrivate();PublicKey publicKey = keyPair.getPublic();return Pair.of(ECKeyUtil.toPrivateParams(privateKey), ECKeyUtil.toPublicParams(publicKey)); }public static ByteString encrypt(byte[] plainText, int offset, int length, ECPublicKeyParameters publicKeyParameters) {SM2Engine sm2Engine = new SM2Engine(Mode.C1C2C3);sm2Engine.init(true, new ParametersWithRandom(publicKeyParameters));try {return ByteString.of(sm2Engine.processBlock(plainText, offset, length));} catch (InvalidCipherTextException var6) {throw new RuntimeException(var6);} }public static ByteString decrypt(byte[] plainText, int offset, int length, ECPrivateKeyParameters privateKeyParameters) {SM2Engine sm2Engine = new SM2Engine(Mode.C1C2C3);sm2Engine.init(false, privateKeyParameters);try {return ByteString.of(sm2Engine.processBlock(plainText, offset, length));} catch (InvalidCipherTextException var6) {throw new RuntimeException(var6);} }
需要注意的是前端在使用官方提供的 sm-crypto 类库时,对加密后的数组使用的是转16进制字符串的形式传递给后端,因此后端在接收到后需要用 Hex.decode 解一把才可使用