RSA加密传输AES的key和iv (补2016年11月)
来源:互联网 发布:网络管理系统 编辑:程序博客网 时间:2024/06/16 23:59
项目包含敏感数据,传输过程要求加密,我们研究了两种算法:AES和RSA
传输过程,也就是指前台到后台
AES,对称加密;只有一把密钥,获得密钥,即可解开加密内容
RSA,非对称加密,有两把密钥,公钥和私钥,获得两把钥匙,才可解开加密内容
RSA对需加密的内容长度有限制,前辈们就采取分段加密,但自己并没有解决遇到的问题,技术研究时间有限,最终项目组采取了以下加密方法:
1.每次请求,随机生成AES的key和iv
2.用RSA的公钥加密AES的key和iv
3.用AES加密向后台请求的参数
4.ajax向后台发送post请求,请求参数有:(1)AES加密的参数 (2)RSA加密的AES的key (3)RSA加密的AES的iv
5.后台RSA私钥解密key和iv
6.后台AES解密前台参数
7.==========================根据参数,读数据库==========================
8.获得内容
9.对内容进行AES加密,返回到前台
10.前台进行AES解密,并展示
11.RSA的公私密钥对需定期更换
以下代码是网上查询和自己思考综合的结果,希望有帮助!
前台代码:
<%@ page language="java" pageEncoding="UTF-8"%><%@ page contentType="text/html; chareset=UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html> <head> <style> *{margin:0;padding:0} .demo-wrap{width: 400px;height: 50px;margin: 50px auto auto auto} </style> <script src="./js/jquery-1.6.4.min.js"></script> <script src="./js/Encryption.js"></script> <script src="./js/RSA.js"></script><script src="./js/BigInt.js"></script><script src="./js/Barrett.js"></script> <script src="./rollups/aes.js"></script> </head> <body> <div class="demo-wrap"> 输入框:<input type="text" id="data-ipt" maxlength="1000000"/> <input type="button" value="提交" onclick="enAES();" /> <br/> 数据获得: <p id="decrypted"></p></div> <script type="text/javascript">function enAES(){var keyRSA = bodyRSA(); //生成RSA加密用的keyvar key = randomString();//随机生成AES的key 和 iv var iv = randomString();var aKey = encryptedString(keyRSA, encodeURIComponent(key)); //RSA加密AES的keyvar aIv = encryptedString(keyRSA, encodeURIComponent(iv)); //RSA加密AES的ivvar inputData = document.getElementById("data-ipt").value; //获取输入框内容 var miwen = getAesString(encodeURIComponent(inputData),key,iv); //AES加密输入框内容 /** 调用后台: ajax */ $.ajax({ url: "/jiami/RSAAES", type: "post", data: {"miwen":miwen,"aKey":aKey,"aIv":aIv}, cache: false, async : false, dataType: "json", success: function (data) { var decryptedStr = getDAesString(data,key,iv); document.getElementById("decrypted").innerHTML = decodeURIComponent(decryptedStr); }, error:function (XMLHttpRequest, textStatus, errorThrown) { alert("与服务器连接失败!"); } });}</script> </body></html>
后台代码:
package com;import java.io.ByteArrayOutputStream;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.UnsupportedEncodingException;import java.math.BigInteger;import java.net.URLDecoder;import java.net.URLEncoder;import java.security.InvalidAlgorithmParameterException;import java.security.InvalidKeyException;import java.security.KeyFactory;import java.security.KeyPair;import java.security.KeyPairGenerator;import java.security.NoSuchAlgorithmException;import java.security.PrivateKey;import java.security.PublicKey;import java.security.SecureRandom;import java.security.interfaces.RSAPrivateKey;import java.security.interfaces.RSAPublicKey;import java.security.spec.InvalidKeySpecException;import java.security.spec.RSAPrivateKeySpec;import java.security.spec.RSAPublicKeySpec;import javax.crypto.BadPaddingException;import javax.crypto.Cipher;import javax.crypto.IllegalBlockSizeException;import javax.crypto.NoSuchPaddingException;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.apache.commons.codec.binary.Base64;import com.google.gson.Gson;public class RSAAES extends HttpServlet{private static final long serialVersionUID = -5657272720504177622L;private static String RSAKeyStore = "C:/RSAKey.txt";protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doPost(req,resp);}protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {request.setCharacterEncoding("UTF-8");//设定客户端提交给servlet的内容按UTF-8编码response.setCharacterEncoding("UTF-8");//设定servlet传回给客户端的内容按UTF-8编码response.setContentType("text/html;charset=UTF-8");//告知浏览器用UTF-8格式解析内容String miwen = request.getParameter("miwen");String aKey = request.getParameter("aKey");String aIv = request.getParameter("aIv");//解密RSA加密的AES的key 和 ivtry {aKey = getString(aKey);aIv = getString(aIv);} catch (Exception e) {e.printStackTrace();}//解密由AES加密的密文 String decrypted = AES_CBC_Decrypt(miwen, aKey.getBytes(), aIv.getBytes()); decrypted = URLDecoder.decode(decrypted,"UTF-8"); System.out.println("解密后:"+decrypted); /** * 根据参数 decrypted ,模拟连接数据库,查得以下内容 */ String yuanCode = "胡歌~!@#¥%……&*()——+=-0987654321·{}:”》?《,。、;’【】、|" + "~!@#$%^&*()_LLL"; //后台AES加密 yuanCode = URLEncoder.encode(yuanCode,"UTF-8");String jiami = AES_CBC_Encrypt(yuanCode,aKey.getBytes(), aIv.getBytes());Gson gson = new Gson();String json = gson.toJson(jiami);response.getWriter().write(json);}/** * AES加密 * @param content 明文 * @param keyBytes 秘钥 * @param iv 偏移量 * @return */ public static String AES_CBC_Encrypt(String content, byte[] keyBytes, byte[] iv){ try{ SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); Cipher cipher=Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv)); byte[] result=cipher.doFinal(content.getBytes()); return new String(Base64.encodeBase64(result),"UTF-8"); }catch (Exception e) { System.out.println("exception:"+e.toString()); } return null; } /** * AES解密 * @param content 密文 * @param keyBytes 秘钥 * @param iv 偏移量 * @return */ public static String AES_CBC_Decrypt(String content, byte[] keyBytes, byte[] iv){ try{ content = content.replaceAll(" ", "+"); byte[] decryptBaseData=Base64.decodeBase64(content.getBytes("utf-8")); SecretKeySpec key = new SecretKeySpec(keyBytes, "AES"); Cipher cipher=Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv)); byte[] result=cipher.doFinal(decryptBaseData); return new String(result); } catch (NoSuchPaddingException e) { e.printStackTrace(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (InvalidKeyException e) { e.printStackTrace(); } catch (IllegalBlockSizeException e) { e.printStackTrace(); } catch (BadPaddingException e) { e.printStackTrace(); } catch (InvalidAlgorithmParameterException e) {e.printStackTrace();} return null; } /** * 字符串转为 byte[] * @param hexString * @return */ public static byte[] hexStringToBytes(String hexString) { if (hexString == null || hexString.equals("")) { return null; } hexString = hexString.toUpperCase(); int length = hexString.length() / 2; char[] hexChars = hexString.toCharArray(); byte[] d = new byte[length]; for (int i = 0; i < length; i++) { int pos = i * 2; d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1])); } return d; } /** * Convert char to byte * * @param c char * @return byte */ private static byte charToByte(char c) { return (byte) "0123456789ABCDEF".indexOf(c); } /** * 解密由RSA加密的AES的key 和 iv * @param para * @return * @throws Exception */ public String getString(String para) throws Exception{byte[] KeyB = hexStringToBytes(para);KeyB = decrypt(getKeyPair().getPrivate(),KeyB);StringBuffer sbKey = new StringBuffer();sbKey.append(new String(KeyB));para = sbKey.reverse().toString();return URLDecoder.decode(para,"UTF-8"); } /** * * 生成密钥对 * * * @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());saveKeyPair(keyPair);return keyPair;} catch (Exception e) {throw new Exception(e.getMessage());}}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;}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 modulus * * @param publicExponent * * @return RSAPublicKey * * @throws Exception */public static RSAPublicKey generateRSAPublicKey(byte[] modulus,byte[] publicExponent) throws Exception {KeyFactory keyFac = null;try {keyFac = KeyFactory.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());} catch (NoSuchAlgorithmException ex) {throw new Exception(ex.getMessage());}RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(new BigInteger(modulus), new BigInteger(publicExponent));try {return (RSAPublicKey) keyFac.generatePublic(pubKeySpec);} catch (InvalidKeySpecException ex) {throw new Exception(ex.getMessage());}}/** * * 生成私钥 * * * @param modulus * * @param privateExponent * * @return RSAPrivateKey * * @throws Exception */public static RSAPrivateKey generateRSAPrivateKey(byte[] modulus,byte[] privateExponent) throws Exception {KeyFactory keyFac = null;try {keyFac = KeyFactory.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());} catch (NoSuchAlgorithmException ex) {throw new Exception(ex.getMessage());}RSAPrivateKeySpec priKeySpec = new RSAPrivateKeySpec(new BigInteger(modulus), new BigInteger(privateExponent));try {return (RSAPrivateKey) keyFac.generatePrivate(priKeySpec);} catch (InvalidKeySpecException ex) {throw new Exception(ex.getMessage());}}/** * * 加密 * * * @param key * 加密的密钥 * * @param data * 待加密的明文数据 * * @return 加密后的数据 * * @throws Exception */public static byte[] encrypt(PublicKey pk, byte[] data) throws Exception {try {Cipher cipher = Cipher.getInstance("RSA",new org.bouncycastle.jce.provider.BouncyCastleProvider());cipher.init(Cipher.ENCRYPT_MODE, pk);int blockSize = cipher.getBlockSize();// 获得加密块大小,如:加密前数据为128个byte,而key_size=1024// 加密块大小为127// byte,加密后为128个byte;因此共有2个加密块,第一个127// byte第二个为1个byteint outputSize = cipher.getOutputSize(data.length);// 获得加密块加密后块大小int leavedSize = data.length % blockSize;int blocksSize = leavedSize != 0 ? data.length / blockSize + 1: data.length / blockSize;byte[] raw = new byte[outputSize * blocksSize];int i = 0;while (data.length - i * blockSize > 0) {if (data.length - i * blockSize > blockSize)cipher.doFinal(data, i * blockSize, blockSize, raw, i* outputSize);elsecipher.doFinal(data, i * blockSize, data.length - i* blockSize, raw, i * outputSize);// 这里面doUpdate方法不可用,查看源代码后发现每次doUpdate后并没有什么实际动作除了把byte[]放到// ByteArrayOutputStream中,而最后doFinal的时候才将所有的byte[]进行加密,可是到了此时加密块大小很可能已经超出了// OutputSize所以只好用dofinal方法。i++;}return raw;} catch (Exception e) {throw new Exception(e.getMessage());}}/** * * 解密 * * * @param key * 解密的密钥 * * @param raw * 已经加密的数据 * * @return 解密后的明文 * * @throws Exception */@SuppressWarnings("static-access")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());}}}
源码下载点击这里
RSA加密文件下载
0 0
- RSA加密传输AES的key和iv (补2016年11月)
- CryptoJS aes加密,需key 和偏移量 iv
- js的RSA和AES加密解密
- RSA和AES加密解密
- 整理的AES对称加密和RSA非对称加密
- AES加密原文,RSA加密AES的秘钥
- java RSA和AES加密解密工具
- 关于Android侧使用AES进行加解密时的key和iv使用的方法
- PHP的AES/RSA加密解密算法
- AES与RSA加密
- AES/RSA加密机制
- 非对称加密RSA和对称加密AES,没你想象的那么神秘
- Android 中 非对称(RSA)加密和对称(AES)加密
- Android 中 非对称(RSA)加密和对称(AES)加密
- 非对称加密(RSA)与对称加密(AES)的应用
- RSA和AES在c#服务端和android客户端之间的加密解密
- 利用openssl的AES和RSA完成对数据的加密解密
- 典型的网络接口安全机制,AES和RSA混合加密
- node-express
- 堆相关的一些操作
- Pixy原理及Opencv实现
- SVG实现超酷素描动画
- JAVA基础题目
- RSA加密传输AES的key和iv (补2016年11月)
- 夕拾算法进阶篇:15)最长公共子序列(动态规划DP)
- 笔记:运算符的重载
- Oracle之用户管理
- hdu1394 -Minimum Inversion Number(线段树求逆序数)
- Andrew Ng教你如何学习机器学习——Quora问答
- 【笔试练习】去哪儿笔试题
- hdu1083【二分图】【最大匹配】
- Messagebox