RSA加密传输AES的key和iv (补2016年11月)
2017-02-01 17:37
369 查看
项目包含敏感数据,传输过程要求加密,我们研究了两种算法: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的公私密钥对需定期更换
以下代码是网上查询和自己思考综合的结果,希望有帮助!
前台代码:
后台代码:
源码下载点击这里
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加密用的key var key = randomString();//随机生成AES的key 和 iv var iv = randomString(); var aKey = encryptedString(keyRSA, encodeURIComponent(key)); //RSA加密AES的key var aIv = encryptedString(keyRSA, encodeURIComponent(iv)); //RSA加密AES的iv var 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 和 iv try { 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个byte int 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); else cipher.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加密文件下载
相关文章推荐
- 利用OpenSSL库对Socket传输进行安全加密(RSA+AES)
- 利用OpenSSL库对Socket传输进行安全加密(RSA+AES)
- 数据传输加密非对称加密算法以及对称算法-RSA+AES
- 利用OpenSSL库对Socket传输进行安全加密(RSA+AES)
- 数据传输加密:非对称加密算法RSA+对称算法AES(适用于java,android和Web)
- [置顶] 数据传输加密——非对称加密算法RSA+对称算法AES(适用于java,android和Web)
- 利用OpenSSL库对Socket传输进行安全加密(RSA+AES)
- CryptoJS aes加密,需key 和偏移量 iv
- 我的Android进阶之旅------>Android采用AES+RSA的加密机制对http请求进行加密
- 加密 解密 RSA & AES & DES
- 使用openssl中的加密函数AES、RC4、RSA对文件加密的一个例子
- 加密解密算法【RSA、AES、DES、MD5】介绍和使用
- RSA加密Socket传输文件、签名(四)
- jQuery+C#实现参数RSA加密传输功能【附jsencrypt.js下载】
- iOS-关于MD5加密,AES加密,RSA加签验签
- 几种通信加密的方法(Key Agreement Protocol, Digital Signatures, RSA from Blown to Bits)
- Java对称与非对称加密解密,AES与RSA
- Js参数RSA加密传输,jsencrypt.js的使用
- DES、AES、RSA加密解密