package org.springblade.common.utils; import java.io.UnsupportedEncodingException; import java.math.BigInteger; import java.net.URLDecoder; import java.net.URLEncoder; import java.security.InvalidParameterException; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.PrivateKey; import java.security.Provider; import java.security.SecureRandom; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import javax.crypto.Cipher; import org.apache.commons.lang3.StringUtils; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.util.encoders.Hex; /** * RSA算法加密/解密工具类。 * 以下代码可以使用,唯一需要注意的是: org.bouncycastle...这个jar包需要找一到放到项目中,RSA所需jar包在java中已经自带了. * * @author liuyan */ public class RSAUtils { /** * 算法名称 */ private static final String ALGORITHOM = "RSA"; /** * 密钥大小 */ private static final int KEY_SIZE = 1024; /** * 默认的安全服务提供者 */ private static final Provider DEFAULT_PROVIDER = new BouncyCastleProvider(); private static KeyPairGenerator keyPairGen = null; private static KeyFactory keyFactory = null; /** * 缓存的密钥对。 */ private static KeyPair oneKeyPair = null; //密文种子, 当想更换RSA钥匙的时候,只需要修改密文种子,即可更换 private static final String radamKey = "你自己随便写上数字或者英文即可"; //类加载后进行初始化数据 static { try { keyPairGen = KeyPairGenerator.getInstance(ALGORITHOM, DEFAULT_PROVIDER); keyFactory = KeyFactory.getInstance(ALGORITHOM, DEFAULT_PROVIDER); } catch (NoSuchAlgorithmException ex) { ex.printStackTrace(); } } /** * 根据指定的密文种子,生成并返回RSA密钥对。 */ private static synchronized KeyPair generateKeyPair() { try { keyPairGen.initialize(KEY_SIZE, new SecureRandom(radamKey.getBytes())); oneKeyPair = keyPairGen.generateKeyPair(); return oneKeyPair; } catch (InvalidParameterException ex) { ex.printStackTrace(); } catch (NullPointerException ex) { ex.printStackTrace(); } return null; } /** * 返回初始化时默认的公钥。 */ public static RSAPublicKey getDefaultPublicKey() { KeyPair keyPair = generateKeyPair(); if (keyPair != null) { return (RSAPublicKey) keyPair.getPublic(); } return null; } /** * 使用指定的私钥解密数据。 * * @param privateKey 给定的私钥。 * @param data 要解密的数据。 * @return 原数据。 */ public static byte[] decrypt(PrivateKey privateKey, byte[] data) throws Exception { Cipher ci = Cipher.getInstance(ALGORITHOM, DEFAULT_PROVIDER); ci.init(Cipher.DECRYPT_MODE, privateKey); return ci.doFinal(data); } /** * 使用默认的私钥解密给定的字符串。 * @param encryptText 密文。 * @return 原文字符串。 */ public static String decryptString(String encryptText) { if (StringUtils.isBlank(encryptText)) { return null; } KeyPair keyPair = generateKeyPair(); try { byte[] en_data = Hex.decode(encryptText); byte[] data = decrypt((RSAPrivateKey) keyPair.getPrivate(), en_data); return new String(data); } catch (NullPointerException ex) { ex.printStackTrace(); } catch (Exception ex) { ex.printStackTrace(); } return null; } /** * 使用秘钥 - 对js端传递过来密文进行解密 * * @param encryptText 密文。 * @return {@code encryptText} 的原文字符串。 */ public static String decryptStringByJs(String encryptText) { String text = decryptString(encryptText); if (text == null) { return null; } String reverse = StringUtils.reverse(text); String decode = null; try { //这里需要进行编码转换.注:在前端js对明文加密前需要先进行转码-可自行百度"编码转换" decode = URLDecoder.decode(reverse, "UTF-8"); System.out.println("解密后文字:" + decode); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return decode; } //java端 - 使用公钥进行加密 public static byte[] encrypt(String plaintext) throws Exception { // 获取公钥及参数e,n RSAPublicKey publicKey = RSAUtils.getDefaultPublicKey(); //获取公钥指数 e BigInteger e = publicKey.getPublicExponent(); //获取公钥系数 n BigInteger n = publicKey.getModulus(); //先将明文进行编码 String encode = URLEncoder.encode(plaintext); // 获取明文字节数组 m BigInteger m = new BigInteger(encode.getBytes()); // 进行明文加密 c BigInteger c = m.modPow(e, n); //返回密文字节数组 return c.toByteArray(); } //java端 - 使用私钥进行解密 public static String decrypt(byte[] cipherText) throws Exception { // 读取私钥 KeyPair keyPair = generateKeyPair(); RSAPrivateKey prk = (RSAPrivateKey) keyPair.getPrivate(); // 获取私钥参数-指数/系数 BigInteger d = prk.getPrivateExponent(); BigInteger n = prk.getModulus(); // 读取密文 BigInteger c = new BigInteger(cipherText); // 进行解密 BigInteger m = c.modPow(d, n); // 解密结果-字节数组 byte[] mt = m.toByteArray(); //转成String,此时是乱码 String en = new String(mt); //再进行编码 String result = java.net.URLDecoder.decode(en, "UTF-8"); //最后返回解密后得到的明文 return result; } public static void main(String[] args) { /*解密js端传递过来的密文*/ //获取公钥对象--注意:前端那边需要用到公钥系数和指数 RSAPublicKey publicKey = RSAUtils.getDefaultPublicKey(); //公钥-系数(n) System.out.println("public key modulus:" + new String(Hex.encode(publicKey.getModulus().toByteArray()))); //公钥-指数(e1) System.out.println("public key exponent:" + new String(Hex.encode(publicKey.getPublicExponent().toByteArray()))); //JS加密后的字符串 String param = "8c49dfb92a0c8d15b0187b1eabc343a80f340962ebecc497205f83f6a4792141d4e711b6d439388ecf691df4eda2cae1e6431573b61e3f564ffe1c757e32f3e846b5983e5939ddeb28c9570001d7f208ffbaa069677d363cc73e4c78c0d508e8b0b9f6205473269bbfbc22e7fb9413be4c449520eb6cfb4fbbff4e7e189a005a"; //解密后的字符串 String param1 = RSAUtils.decryptStringByJs(param); /*后端的加密和解密-在加密的方法中已经使用了公钥指数和系数*/ try { //加密 byte[] param3 = encrypt("你好> @# !!# #"); //解密 String decrypt = RSAUtils.decrypt(param3); System.out.println(decrypt); } catch (Exception e) { e.printStackTrace(); } } }