`
齐晓威_518
  • 浏览: 606910 次
  • 性别: Icon_minigender_1
  • 来自: 郑州
社区版块
存档分类
最新评论

web 前端 javascript RSA加密提交数据,server端用java解密

 
阅读更多

前几天user有个要求,就是系统中所有的密码输入框的内容(password) 必须加密提交。即使用工具能抓取到request,但是抓取到的password 都是密文。

 

 

首先了解:RSA加密算法的精髓是什么 

对称加密。 密钥不是一个,而是一对,A和B。使用A加密的密文只能使用B来解密。使用B加密的密文只能使用A来解密。选择其中的一个作为公钥,另一个作为私钥,可以用于许多非对称加密应用场合。比如电子证书、电子指纹、电子签名、握手协议等传统对称加密手段无法实现的功能。

其核心是基于“大数的分解质因数非常困难”这个数学难题。使得在得知A的人无法推算出B,B也无法推算出A。

为此:找了很多解决方案,最终采用的如下

web 前端 javascript RSA加密提交数据,server端用java解密

采用的第三方组件及jar

1.jquery-1.6.js

2.jquery.jcryption-1.1.js

jar files:

3.bcprov-ext-jdk15on-148.jar

4.bcprov-jdk15on-148.jar

 

步骤:

第一:当系统在加载页面完成后,如果发现页面中包含密码框,则向server发起请求来获取key--用于js加密。此key要存于session中,以便server解密。

第二:当密码框在输入密码失焦时,调用js加密。在提交的时候,check password是否加密。阻止明文提交。

第三:server在收到请求后,对密文进行解密。

 

js code:

Js代码   收藏代码
  1. var keys;  
  2.   
  3. $(function(){  
  4.     var hasPass = $('input:password');  
  5.     var token = $('#csrfToken').val();  
  6.       
  7.     getKeys();  
  8.       
  9.     $(hasPass).each(function(index){  
  10.         var currentItem = $(this);  
  11.         $(currentItem).focus(function(){  
  12.             $(currentItem).val("");  
  13.         });  
  14.         $(currentItem).blur(function(){  
  15.             var cVal = $(currentItem).val();  
  16.             if($.trim(cVal) != "" && "undefined" != keys && null != keys){  
  17.                 $.jCryption.encrypt($(currentItem).val(), keys, function(encryptedPasswd) {  
  18.                     $(currentItem).val(encryptedPasswd);  
  19.                 });  
  20.             }  
  21.         });  
  22.     });  
  23. });  
  24.   
  25. function getKeys() {  
  26.     $.jCryption.getKeys(URL,function(receivedKeys) {  
  27.         keys = receivedKeys;  
  28.     });  
  29.       
  30. }  
  31. function submitForm(form){  
  32.     var flag = true;  
  33.     //check password is encrypt or not  
  34.     var Cpass;  
  35.     $(form).find("input:password").each(function(index){  
  36.         var currPass = $(this);  
  37.         var value = $.trim($(currPass).val());  
  38.         var reg = /^[A-Za-z0-9]{128}$/;  
  39.         if(value == ""){  
  40.             flag = false;  
  41.             Cpass = $(currPass);  
  42.         }else if(!reg.test(value)){  
  43.             //the reason maybe previous request gain public key failed  
  44.             //so please check - public key via ajax request.-(getKey(val))  
  45.             //alert("key-->"+keys);  
  46.             alert("encrypt failed.");  
  47.             flag = false;  
  48.         }  
  49.     });  
  50.     if(flag == true){  
  51.         form.submit();  
  52.     }else{  
  53.         if(undefined != Cpass && null != Cpass && $(Cpass).val() == ""){  
  54.             alert("Please key in your password.");  
  55.             $(Cpass).focus();  
  56.         }else{//redirect to login page  
  57.             var url = window.location.href;  
  58.             //there can do clear form ...  
  59.             window.location.href = url+"?request=Login";  
  60.         }  
  61.     }  
  62. }  

 

加密解密工具类

Java代码   收藏代码
  1. package util.jsRSAjava;  
  2.   
  3. import java.io.UnsupportedEncodingException;  
  4. import java.net.URLDecoder;  
  5. import java.security.GeneralSecurityException;  
  6. import java.security.KeyPair;  
  7. import java.security.KeyPairGenerator;  
  8. import java.security.NoSuchAlgorithmException;  
  9. import java.security.interfaces.RSAPublicKey;  
  10. import java.util.HashMap;  
  11. import java.util.Map;  
  12.   
  13. import javax.crypto.Cipher;  
  14.   
  15.   
  16. /** 
  17.  * @author hbkeepmoving@hotmail.com 
  18.  *  
  19.  */  
  20. public class JCryptionUtil {  
  21.       
  22.     public static final java.security.Provider provider = new org.bouncycastle.jce.provider.BouncyCastleProvider();  
  23.     /** 
  24.      * Constructor 
  25.      */  
  26.     public JCryptionUtil() throws Exception {  
  27.         java.security.Security.addProvider(provider);  
  28.     }  
  29.   
  30.     /** 
  31.      * Generates the Keypair with the given keyLength. 
  32.      *  
  33.      * @param keyLength 
  34.      *            length of key 
  35.      * @return KeyPair object 
  36.      * @throws RuntimeException 
  37.      *             if the RSA algorithm not supported 
  38.      */  
  39.     public KeyPair generateKeypair(int keyLength) throws Exception {  
  40.         try {  
  41.             KeyPairGenerator kpg;   
  42.             try {  
  43.                 kpg = KeyPairGenerator.getInstance("RSA");  
  44.             } catch (Exception e) {  
  45.                 kpg = KeyPairGenerator.getInstance("RSA",provider);  
  46.             }  
  47.             kpg.initialize(keyLength);  
  48.             KeyPair keyPair = kpg.generateKeyPair();  
  49.             return keyPair;  
  50.         } catch (NoSuchAlgorithmException e1) {  
  51.             throw new RuntimeException("RSA algorithm not supported", e1);  
  52.         } catch (Exception e) {  
  53.             throw new Exception("other exceptions", e);  
  54.         }  
  55.     }  
  56.   
  57.     /** 
  58.      * Decrypts a given string with the RSA keys 
  59.      *  
  60.      * @param encrypted 
  61.      *            full encrypted text 
  62.      * @param keys 
  63.      *            RSA keys 
  64.      * @return decrypted text 
  65.      * @throws RuntimeException 
  66.      *             if the RSA algorithm not supported or decrypt operation failed 
  67.      */  
  68.     public static String decrypt(String encrypted, KeyPair keys) throws Exception {  
  69.         Cipher dec;  
  70.         try {  
  71.             try {  
  72.                 dec = Cipher.getInstance("RSA/NONE/NoPadding");  
  73.             } catch (Exception e) {  
  74.                 dec = Cipher.getInstance("RSA/NONE/NoPadding",provider);  
  75.             }  
  76.             dec.init(Cipher.DECRYPT_MODE, keys.getPrivate());  
  77.         } catch (GeneralSecurityException e) {  
  78.             throw new RuntimeException("RSA algorithm not supported", e);  
  79.         }  
  80.         String[] blocks = encrypted.split("\\s");  
  81.         StringBuffer result = new StringBuffer();  
  82.         try {  
  83.             for (int i = blocks.length - 1; i >= 0; i--) {  
  84.                 byte[] data = hexStringToByteArray(blocks[i]);  
  85.                 byte[] decryptedBlock = dec.doFinal(data);  
  86.                 result.append(new String(decryptedBlock));  
  87.             }  
  88.         } catch (GeneralSecurityException e) {  
  89.             throw new RuntimeException("Decrypt error", e);  
  90.         }  
  91.         /** 
  92.          * Some code is getting added in first 2 digits with Jcryption need to investigate 
  93.          */  
  94.         return result.reverse().toString().substring(2);  
  95.     }  
  96.   
  97.     /** 
  98.      * Parse url string (Todo - better parsing algorithm) 
  99.      *  
  100.      * @param url 
  101.      *            value to parse 
  102.      * @param encoding 
  103.      *            encoding value 
  104.      * @return Map with param name, value pairs 
  105.      */  
  106.     public static Map parse(String url, String encoding) {  
  107.         try {  
  108.             String urlToParse = URLDecoder.decode(url, encoding);  
  109.             String[] params = urlToParse.split("&");  
  110.             Map parsed = new HashMap();  
  111.             for (int i = 0; i < params.length; i++) {  
  112.                 String[] p = params[i].split("=");  
  113.                 String name = p[0];  
  114.                 String value = (p.length == 2) ? p[1] : null;  
  115.                 parsed.put(name, value);  
  116.             }  
  117.             return parsed;  
  118.         } catch (UnsupportedEncodingException e) {  
  119.             throw new RuntimeException("Unknown encoding.", e);  
  120.         }  
  121.     }  
  122.   
  123.     /** 
  124.      * Return public RSA key modulus 
  125.      *  
  126.      * @param keyPair 
  127.      *            RSA keys 
  128.      * @return modulus value as hex string 
  129.      */  
  130.     public static String getPublicKeyModulus(KeyPair keyPair) {  
  131.         RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  
  132.         return publicKey.getModulus().toString(16);  
  133.     }  
  134.   
  135.     /** 
  136.      * Return public RSA key exponent 
  137.      *  
  138.      * @param keyPair 
  139.      *            RSA keys 
  140.      * @return public exponent value as hex string 
  141.      */  
  142.     public static String getPublicKeyExponent(KeyPair keyPair) {  
  143.         RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  
  144.         return publicKey.getPublicExponent().toString(16);  
  145.     }  
  146.   
  147.     /** 
  148.      * Max block size with given key length 
  149.      *  
  150.      * @param keyLength 
  151.      *            length of key 
  152.      * @return numeber of digits 
  153.      */  
  154.     public static int getMaxDigits(int keyLength) {  
  155.         return ((keyLength * 2) / 16) + 3;  
  156.     }  
  157.   
  158.     /** 
  159.      * Convert byte array to hex string 
  160.      *  
  161.      * @param bytes 
  162.      *            input byte array 
  163.      * @return Hex string representation 
  164.      */  
  165.     public static String byteArrayToHexString(byte[] bytes) {  
  166.         StringBuffer result = new StringBuffer();  
  167.         for (int i = 0; i < bytes.length; i++) {  
  168.             result.append(Integer.toString((bytes[i] & 0xff) + 0x10016)  
  169.                     .substring(1));  
  170.         }  
  171.         return result.toString();  
  172.     }  
  173.   
  174.     /** 
  175.      * Convert hex string to byte array 
  176.      *  
  177.      * @param data 
  178.      *            input string data 
  179.      * @return bytes 
  180.      */  
  181.     public static byte[] hexStringToByteArray(String data) {  
  182.         int k = 0;  
  183.         byte[] results = new byte[data.length() / 2];  
  184.         for (int i = 0; i < data.length();) {  
  185.             results[k] = (byte) (Character.digit(data.charAt(i++), 16) << 4);  
  186.             results[k] += (byte) (Character.digit(data.charAt(i++), 16));  
  187.             k++;  
  188.         }  
  189.         return results;  
  190.     }  
  191.   
  192.     /** 
  193.      * @param args 
  194.      */  
  195. //  public static void main(String[] args) {  
  196. //      JCryptionUtil jCryption = new JCryptionUtil();  
  197. //      System.out.println(jCryption.toPublicKeyString());  
  198. //  }  
  199.   
  200.     /** 
  201.      * @return 
  202.      */  
  203.     public String toPublicKeyString() throws Exception {  
  204.         KeyPair keys = generateKeypair(512);  
  205.         StringBuffer out = new StringBuffer();  
  206.   
  207.         String e = getPublicKeyExponent(keys);  
  208.         String n = getPublicKeyModulus(keys);  
  209.         String md = String.valueOf(getMaxDigits(512));  
  210.   
  211.         out.append("{\"e\":\"");  
  212.         out.append(e);  
  213.         out.append("\",\"n\":\"");  
  214.         out.append(n);  
  215.         out.append("\",\"maxdigits\":\"");  
  216.         out.append(md);  
  217.         out.append("\"}");  
  218.   
  219.         return out.toString();  
  220.     }  
  221.   
  222. }  

 

生成key的serverlet 代码。很简单。

Java代码   收藏代码
  1. JCryptionUtil jCryptionUtil = new JCryptionUtil();  
  2. KeyPair keys = null;  
  3. keys = jCryptionUtil.generateKeypair(512);  
  4. request.getSession().setAttribute("keys", keys);  
  5. StringBuffer output = new StringBuffer();  
  6. String e = JCryptionUtil.getPublicKeyExponent(keys);  
  7. String n = JCryptionUtil.getPublicKeyModulus(keys);  
  8. String md = String.valueOf(JCryptionUtil.getMaxDigits(512));  
  9. output.append("{\"e\":\"");  
  10. output.append(e);  
  11. output.append("\",\"n\":\"");  
  12. output.append(n);  
  13. output.append("\",\"maxdigits\":\"");  
  14. output.append(md);  
  15. output.append("\"}");  
  16. output.toString();  
  17. response.getOutputStream().print(output.toString().replaceAll("\r""").replaceAll("\n""").trim());  

 

解密的servlet中代码,当然也可在写在filter中

Java代码   收藏代码
  1. String pass = request.getParameter("pass");//login pass  
  2. KeyPair keys = (KeyPair) SessionUtility.getSession(request).getAttribute("keys");  
  3. String decryptedPass = JCryptionUtil.decrypt(pass, keys);  
  4. request.setAttribute("pass", decryptedPass);  

 

到此,就处理了。

现在我不知道,还有没有更好的解决方法。。。。各位大神多指点哈。。

 

 

 

 

另外:如果自己project 会部署到其他系统(eg:unix.....etc),如果在获取key失败,检查一下server log。如果有securityPermission的exception的话。

请参考

http://hb-keepmoving.iteye.com/blog/1851179

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics