diff --git a/common/src/main/java/com/jeesite/common/codec/RsaUtils.java b/common/src/main/java/com/jeesite/common/codec/RsaUtils.java new file mode 100644 index 00000000..4936584f --- /dev/null +++ b/common/src/main/java/com/jeesite/common/codec/RsaUtils.java @@ -0,0 +1,185 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + */ +package com.jeesite.common.codec; + +import com.jeesite.common.io.PropertiesUtils; + +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.nio.charset.StandardCharsets; +import java.security.*; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; + +/** + * RSA 加密解密工具类,非对称加密 + * @author ThinkGem + */ +public class RsaUtils { + + private static final String RSA = "RSA"; + private static final String algorithm = "SHA256withRSA"; + private static final boolean STORE_BASE64 = PropertiesUtils.getInstance() + .getPropertyToBoolean("encrypt.storeBase64", "false"); + + /** + * 生成 RSA 秘钥对 + */ + public static String[] genKeys() { + try { + KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(RSA); + keyPairGenerator.initialize(1024); + KeyPair keyPair = keyPairGenerator.generateKeyPair(); + PublicKey publicKey = keyPair.getPublic(); + PrivateKey privateKey = keyPair.getPrivate(); + return new String[]{ + EncodeUtils.encodeBase64(publicKey.getEncoded()), + EncodeUtils.encodeBase64(privateKey.getEncoded()), + }; + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + /** + * 将 Base64 公钥串,转化为公钥对象 + * @author ThinkGem + */ + public static PublicKey toPublicKey(String publicKey) { + try { + KeyFactory keyFactory = KeyFactory.getInstance(RSA); + X509EncodedKeySpec publicKeySpec = new X509EncodedKeySpec(EncodeUtils.decodeBase64(publicKey)); + return keyFactory.generatePublic(publicKeySpec); + } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + /** + * 将 Base64 私钥串,转化为私钥对象 + * @author ThinkGem + */ + public static PrivateKey toPrivateKey(String privateKey) { + try { + KeyFactory keyFactory = KeyFactory.getInstance(RSA); + PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(EncodeUtils.decodeBase64(privateKey)); + return keyFactory.generatePrivate(pkcs8EncodedKeySpec); + } catch (InvalidKeySpecException | NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + } + + /** + * 公钥加密 + * @author ThinkGem + */ + public static byte[] encode(byte[] input, PublicKey publicKey) { + try { + Cipher encryptCipher = Cipher.getInstance(RSA); + encryptCipher.init(Cipher.ENCRYPT_MODE, publicKey); + return encryptCipher.doFinal(input); + } catch (InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | + NoSuchAlgorithmException | BadPaddingException e) { + throw new RuntimeException(e); + } + } + + /** + * 公钥加密 + * @author ThinkGem + */ + public static String encode(String input, PublicKey publicKey) { + if (STORE_BASE64) { + return EncodeUtils.encodeBase64(encode(input.getBytes(StandardCharsets.UTF_8), publicKey)); + } + return EncodeUtils.encodeHex(encode(input.getBytes(StandardCharsets.UTF_8), publicKey)); + } + + /** + * 私钥解密 + * @author ThinkGem + */ + public static byte[] decode(byte[] input, PrivateKey privateKey) { + return decodeImpl(input, privateKey); + } + + private static byte[] decodeImpl(byte[] input, PrivateKey privateKey) { + try { + Cipher decryptCipher = Cipher.getInstance(RSA); + decryptCipher.init(Cipher.DECRYPT_MODE, privateKey); + return decryptCipher.doFinal(input); + } catch (InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | + NoSuchAlgorithmException | BadPaddingException e) { + throw new RuntimeException(e); + } + } + + /** + * 私钥解密 + * @author ThinkGem + */ + public static String decode(String input, PrivateKey privateKey) { + if (STORE_BASE64) { + return new String(decode(EncodeUtils.decodeBase64(input), privateKey), StandardCharsets.UTF_8); + } + return new String(decode(EncodeUtils.decodeHex(input), privateKey), StandardCharsets.UTF_8); + } + + /** + * 私钥签名 + * @author ThinkGem + */ + public static byte[] sign(byte[] input, PrivateKey privateKey) { + try { + Signature sig = Signature.getInstance(algorithm); + sig.initSign(privateKey); + sig.update(input); + return sig.sign(); + } catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) { + throw new RuntimeException(e); + } + } + + /** + * 私钥签名 + * @author ThinkGem + */ + public static String sign(String input, PrivateKey privateKey) { + if (STORE_BASE64) { + return EncodeUtils.encodeBase64(sign(input.getBytes(StandardCharsets.UTF_8), privateKey)); + } + return EncodeUtils.encodeHex(sign(input.getBytes(StandardCharsets.UTF_8), privateKey)); + } + + /** + * 公钥验签 + * @author ThinkGem + */ + public static boolean verify(byte[] input, PublicKey publicKey, byte[] signature) { + try { + Signature sig = Signature.getInstance(algorithm); + sig.initVerify(publicKey); + sig.update(input); + return sig.verify(signature); + } catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) { + throw new RuntimeException(e); + } + } + + /** + * 公钥验签 + * @author ThinkGem + */ + public static boolean verify(String input, PublicKey publicKey, String signature) { + if (STORE_BASE64) { + return verify(input.getBytes(StandardCharsets.UTF_8), publicKey, EncodeUtils.decodeBase64(signature)); + } + return verify(input.getBytes(StandardCharsets.UTF_8), publicKey, EncodeUtils.decodeHex(signature)); + } + +} \ No newline at end of file diff --git a/common/src/test/java/com/jeesite/test/codec/RsaUtilsTest.java b/common/src/test/java/com/jeesite/test/codec/RsaUtilsTest.java new file mode 100644 index 00000000..b2d586a4 --- /dev/null +++ b/common/src/test/java/com/jeesite/test/codec/RsaUtilsTest.java @@ -0,0 +1,46 @@ +/** + * Copyright (c) 2013-Now http://jeesite.com All rights reserved. + * No deletion without permission, or be held responsible to law. + */ +package com.jeesite.test.codec; + +import com.jeesite.common.codec.EncodeUtils; +import com.jeesite.common.codec.RsaUtils; + +import java.nio.charset.StandardCharsets; +import java.security.PrivateKey; +import java.security.PublicKey; + +/** + * RSA 加密解密工具类,非对称加密 + * @author ThinkGem + */ +public class RsaUtilsTest { + + public static void main(String[] args) { + + String s = "Hello word! 你好,中文!"; + System.out.println(s); + + String[] keys = RsaUtils.genKeys(); + System.out.println("公钥:" + keys[0]); + PublicKey publicKey = RsaUtils.toPublicKey(keys[0]); + System.out.println("私钥:" + keys[1]); + PrivateKey privateKey = RsaUtils.toPrivateKey(keys[1]); + + byte[] data = RsaUtils.encode(s.getBytes(), publicKey); + String dataString = EncodeUtils.encodeBase64(data); + System.out.println("加密数据:" + dataString); + + byte[] data2 = RsaUtils.decode(data, privateKey); + String dataString2 = new String(data2, StandardCharsets.UTF_8); + System.out.println("解密数据:" + dataString2); + + byte[] sign = RsaUtils.sign(s.getBytes(), privateKey); + System.out.println("数据签名:" + EncodeUtils.encodeBase64(sign)); + + boolean b = RsaUtils.verify(s.getBytes(), publicKey, sign); + System.out.println("数据验签:" + b); + } + +} \ No newline at end of file