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" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>RSA测试</title>
<script type="text/javascript" src="js/comm/RSA.js"></script>
<script type="text/javascript" src="js/comm/BigInt.js"></script>
<script type="text/javascript" src="js/comm/Barrett.js"></script>

<script type="text/javascript">
	function rsalogin(){
		var thisPwd = document.getElementById("password").value;
		bodyRSA(); //获得公钥
		var result = encryptedString(key, thisPwd);//加密
		document.getElementById("result").value = result;
		alert(thisPwd+"\r\n"+result);
		loginForm.action="/RSAWeb/TestSer";//访问的servlet路径
		loginForm.submit();//提交
	}
	
	var key ;
	function bodyRSA(){
        //与后台密钥长度成正比
		setMaxDigits(130);
		//参数传值('exponent', '', 'Modulus')
	  	key = new RSAKeyPair("<%=UtilsRSA.getPublicExponent() %>","","<%=UtilsRSA.getPublicModulus() %>"); 
	}
</script>
</head>
<body>
	<form method="post" name="loginForm" target=_blank>
		<table border="0">
			<tr>
				<td>
					Password:
				</td>
				<td>
					<input type='text' name="password" id="password" style='width:300px' value=""/>
					<input type="hidden" name="result" id="result" />
				</td>
			</tr>
			<tr>
				<td colspan="2" align="center">
					<input type="button" value="SUBMIT" onclick="rsalogin();" />
				</td>
			</tr>
		</table>
	</form>
</body>
</html>



后台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!");
	}

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值