RSA前端加密后端解密

RSA是非对称加密,关于它的算法原理。可以查看这个博客链接,我是没看懂(本人数学太差)。

这里介绍下简单的实现方式。

前端需要导入RSA.js、BigInt.js、Barrett.js 。后端需要 依赖 bcprov-jdk15on-160.jar 。js与jar包百度云分享。

这是后端的工具类方法

public class UtilsRSA {
	
	private static String RSAKeyStore = "E:/RSAKey.txt";
	/**
	 * * 生成密钥对 *
	 * @return KeyPair *
	 * @throws EncryptException
	 */
	public static KeyPair generateKeyPair() throws Exception {
		try {
			KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA",
					new org.bouncycastle.jce.provider.BouncyCastleProvider());
			final int KEY_SIZE = 1024;// 没什么好说的了,这个值关系到块加密的大小,可以更改,但是不要太大,否则效率会低
			keyPairGen.initialize(KEY_SIZE, new SecureRandom());
			KeyPair keyPair = keyPairGen.generateKeyPair();
//			System.out.println(keyPair.getPrivate());
//			System.out.println(keyPair.getPublic());
//			System.out.println("getModulus");
//			RSAPublicKey rsapublicKey = (RSAPublicKey) keyPair.getPublic();
//			System.out.println(rsapublicKey.getModulus());
//			System.out.println("十六进制=>"+UtilsRSA.intToHex(rsapublicKey.getModulus()));
//			System.out.println("getPublicExponent");
//			System.out.println(rsapublicKey.getPublicExponent());
//			System.out.println("十六进制=>"+UtilsRSA.intToHex(rsapublicKey.getPublicExponent()));
			//保存keyPair
			saveKeyPair(keyPair);
			return keyPair;
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}
	}
	
	//得到PublicModulus
	public static String getPublicModulus() throws Exception {
		FileInputStream fis = new FileInputStream(RSAKeyStore);
		ObjectInputStream oos = new ObjectInputStream(fis);
		KeyPair keyPair = (KeyPair) oos.readObject();
		oos.close();
		fis.close();
		RSAPublicKey rsapublicKey = (RSAPublicKey) keyPair.getPublic();
		return UtilsRSA.intToHex(rsapublicKey.getModulus());
	}
	//得到PublicExponent
	public static String getPublicExponent() throws Exception {
		FileInputStream fis = new FileInputStream(RSAKeyStore);
		ObjectInputStream oos = new ObjectInputStream(fis);
		KeyPair keyPair = (KeyPair) oos.readObject();
		oos.close();
		fis.close();
		RSAPublicKey rsapublicKey = (RSAPublicKey) keyPair.getPublic();
		return UtilsRSA.intToHex(rsapublicKey.getPublicExponent());
	}
	
	//从本地文件中得到KeyPair
	public static KeyPair getKeyPair() throws Exception {
		FileInputStream fis = new FileInputStream(RSAKeyStore);
		ObjectInputStream oos = new ObjectInputStream(fis);
		KeyPair kp = (KeyPair) oos.readObject();
		oos.close();
		fis.close();
		return kp;
	}
 
	//保存在本地文件中(这里写了保存在本地的方式,你也可以保存在session中)
	public static void saveKeyPair(KeyPair kp) throws Exception {
		FileOutputStream fos = new FileOutputStream(RSAKeyStore);
		ObjectOutputStream oos = new ObjectOutputStream(fos);
		// 保存密钥
		oos.writeObject(kp);
		oos.close();
		fos.close();
	}
 
	/**
	 * * 解密 *
	 * 
	 * @param key  解密的密钥 *
	 * @param raw  已经加密的数据 *
	 * @return     解密后的明文 *
	 * @throws     Exception
	 */
	public static byte[] decrypt(PrivateKey pk, byte[] raw) throws Exception {
		try {
			Cipher cipher = Cipher.getInstance("RSA",
					new org.bouncycastle.jce.provider.BouncyCastleProvider());
			cipher.init(cipher.DECRYPT_MODE, pk);
			int blockSize = cipher.getBlockSize();
			ByteArrayOutputStream bout = new ByteArrayOutputStream(64);
			int j = 0;
			while (raw.length - j * blockSize > 0) {
				bout.write(cipher.doFinal(raw, j * blockSize, blockSize));
				j++;
			}
			return bout.toByteArray();
		} catch (Exception e) {
			throw new Exception(e.getMessage());
		}
	}
	
	//把十进制的BigInteger数转换为十六进制的字符串
	private static String intToHex(BigInteger n) {
		BigInteger zero = new BigInteger("0");
		BigInteger bi2 = new BigInteger("16");
        StringBuilder sb = new StringBuilder();
        String a;
        char []b = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        while(n.compareTo(zero) > 0){
        	BigInteger[] arr = n.divideAndRemainder(bi2);
        	int index = Integer.valueOf(arr[1].toString());
            sb = sb.append(b[index]);
            n = arr[0];            
        }
        a = sb.reverse().toString();
        return a;
    }
	
	
	/**
	 * * *
	 * 可以先使用main方法生成一个KeyPair,并保存在本地。方便获取使用(保存方式随你使用);
	 */
	public static void main(String[] args) throws Exception {
		UtilsRSA.generateKeyPair();
	}
}

前端JSP代码。

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8" import="mseas.utils.UtilsRSA" %>




RSA测试







	
Password:

后台servlet处理并解析。

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		try {
			String result = request.getParameter("result");
			System.out.println("原文加密后为:");
			System.out.println("result=>"+result);
			//new BigInteger(result, 16) 这个‘16’代表着 result参数是 16进制的  结果是返回 十进制的
			byte[] en_result = new BigInteger(result, 16).toByteArray();
			System.out.println("转成byte[]" + new String(en_result));
			byte[] de_result = UtilsRSA.decrypt(UtilsRSA.getKeyPair().getPrivate(), en_result);
			System.out.println("还原密文:");
			System.out.println(new String(de_result));
		} catch (Exception e) {
			e.printStackTrace();
		}
		response.getWriter().append("Served at: ").append("End!");
	}

这里还有一份比较详细的代码,百度云分享 分享链接

你可能感兴趣的:(RSA加密)