前几天user有个要求,就是系统中所有的密码输入框的内容(password) 必须加密提交。即使用工具能抓取到request,但是抓取到的password 都是密文。
为此:找了很多解决方案,最终采用的如下
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:
var keys; $(function(){ var hasPass = $('input:password'); var token = $('#csrfToken').val(); getKeys(); $(hasPass).each(function(index){ var currentItem = $(this); $(currentItem).focus(function(){ $(currentItem).val(""); }); $(currentItem).blur(function(){ var cVal = $(currentItem).val(); if($.trim(cVal) != "" && "undefined" != keys && null != keys){ $.jCryption.encrypt($(currentItem).val(), keys, function(encryptedPasswd) { $(currentItem).val(encryptedPasswd); }); } }); }); }); function getKeys() { $.jCryption.getKeys(URL,function(receivedKeys) { keys = receivedKeys; }); } function submitForm(form){ var flag = true; //check password is encrypt or not var Cpass; $(form).find("input:password").each(function(index){ var currPass = $(this); var value = $.trim($(currPass).val()); var reg = /^[A-Za-z0-9]{128}$/; if(value == ""){ flag = false; Cpass = $(currPass); }else if(!reg.test(value)){ //the reason maybe previous request gain public key failed //so please check - public key via ajax request.-(getKey(val)) //alert("key-->"+keys); alert("encrypt failed."); flag = false; } }); if(flag == true){ form.submit(); }else{ if(undefined != Cpass && null != Cpass && $(Cpass).val() == ""){ alert("Please key in your password."); $(Cpass).focus(); }else{//redirect to login page var url = window.location.href; //there can do clear form ... window.location.href = url+"?request=Login"; } } }
加密解密工具类
package util.jsRSAjava; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; import java.security.interfaces.RSAPublicKey; import java.util.HashMap; import java.util.Map; import javax.crypto.Cipher; /** * @author hbkeepmoving@hotmail.com * */ public class JCryptionUtil { public static final java.security.Provider provider = new org.bouncycastle.jce.provider.BouncyCastleProvider(); /** * Constructor */ public JCryptionUtil() throws Exception { java.security.Security.addProvider(provider); } /** * Generates the Keypair with the given keyLength. * * @param keyLength * length of key * @return KeyPair object * @throws RuntimeException * if the RSA algorithm not supported */ public KeyPair generateKeypair(int keyLength) throws Exception { try { KeyPairGenerator kpg; try { kpg = KeyPairGenerator.getInstance("RSA"); } catch (Exception e) { kpg = KeyPairGenerator.getInstance("RSA",provider); } kpg.initialize(keyLength); KeyPair keyPair = kpg.generateKeyPair(); return keyPair; } catch (NoSuchAlgorithmException e1) { throw new RuntimeException("RSA algorithm not supported", e1); } catch (Exception e) { throw new Exception("other exceptions", e); } } /** * Decrypts a given string with the RSA keys * * @param encrypted * full encrypted text * @param keys * RSA keys * @return decrypted text * @throws RuntimeException * if the RSA algorithm not supported or decrypt operation failed */ public static String decrypt(String encrypted, KeyPair keys) throws Exception { Cipher dec; try { try { dec = Cipher.getInstance("RSA/NONE/NoPadding"); } catch (Exception e) { dec = Cipher.getInstance("RSA/NONE/NoPadding",provider); } dec.init(Cipher.DECRYPT_MODE, keys.getPrivate()); } catch (GeneralSecurityException e) { throw new RuntimeException("RSA algorithm not supported", e); } String[] blocks = encrypted.split("\\s"); StringBuffer result = new StringBuffer(); try { for (int i = blocks.length - 1; i >= 0; i--) { byte[] data = hexStringToByteArray(blocks[i]); byte[] decryptedBlock = dec.doFinal(data); result.append(new String(decryptedBlock)); } } catch (GeneralSecurityException e) { throw new RuntimeException("Decrypt error", e); } /** * Some code is getting added in first 2 digits with Jcryption need to investigate */ return result.reverse().toString().substring(2); } /** * Parse url string (Todo - better parsing algorithm) * * @param url * value to parse * @param encoding * encoding value * @return Map with param name, value pairs */ public static Map parse(String url, String encoding) { try { String urlToParse = URLDecoder.decode(url, encoding); String[] params = urlToParse.split("&"); Map parsed = new HashMap(); for (int i = 0; i < params.length; i++) { String[] p = params[i].split("="); String name = p[0]; String value = (p.length == 2) ? p[1] : null; parsed.put(name, value); } return parsed; } catch (UnsupportedEncodingException e) { throw new RuntimeException("Unknown encoding.", e); } } /** * Return public RSA key modulus * * @param keyPair * RSA keys * @return modulus value as hex string */ public static String getPublicKeyModulus(KeyPair keyPair) { RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); return publicKey.getModulus().toString(16); } /** * Return public RSA key exponent * * @param keyPair * RSA keys * @return public exponent value as hex string */ public static String getPublicKeyExponent(KeyPair keyPair) { RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic(); return publicKey.getPublicExponent().toString(16); } /** * Max block size with given key length * * @param keyLength * length of key * @return numeber of digits */ public static int getMaxDigits(int keyLength) { return ((keyLength * 2) / 16) + 3; } /** * Convert byte array to hex string * * @param bytes * input byte array * @return Hex string representation */ public static String byteArrayToHexString(byte[] bytes) { StringBuffer result = new StringBuffer(); for (int i = 0; i < bytes.length; i++) { result.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16) .substring(1)); } return result.toString(); } /** * Convert hex string to byte array * * @param data * input string data * @return bytes */ public static byte[] hexStringToByteArray(String data) { int k = 0; byte[] results = new byte[data.length() / 2]; for (int i = 0; i < data.length();) { results[k] = (byte) (Character.digit(data.charAt(i++), 16) << 4); results[k] += (byte) (Character.digit(data.charAt(i++), 16)); k++; } return results; } /** * @param args */ // public static void main(String[] args) { // JCryptionUtil jCryption = new JCryptionUtil(); // System.out.println(jCryption.toPublicKeyString()); // } /** * @return */ public String toPublicKeyString() throws Exception { KeyPair keys = generateKeypair(512); StringBuffer out = new StringBuffer(); String e = getPublicKeyExponent(keys); String n = getPublicKeyModulus(keys); String md = String.valueOf(getMaxDigits(512)); out.append("{\"e\":\""); out.append(e); out.append("\",\"n\":\""); out.append(n); out.append("\",\"maxdigits\":\""); out.append(md); out.append("\"}"); return out.toString(); } }
生成key的serverlet 代码。很简单。
JCryptionUtil jCryptionUtil = new JCryptionUtil(); KeyPair keys = null; keys = jCryptionUtil.generateKeypair(512); request.getSession().setAttribute("keys", keys); StringBuffer output = new StringBuffer(); String e = JCryptionUtil.getPublicKeyExponent(keys); String n = JCryptionUtil.getPublicKeyModulus(keys); String md = String.valueOf(JCryptionUtil.getMaxDigits(512)); output.append("{\"e\":\""); output.append(e); output.append("\",\"n\":\""); output.append(n); output.append("\",\"maxdigits\":\""); output.append(md); output.append("\"}"); output.toString(); response.getOutputStream().print(output.toString().replaceAll("\r", "").replaceAll("\n", "").trim());
解密的servlet中代码,当然也可在写在filter中
String pass = request.getParameter("pass");//login pass KeyPair keys = (KeyPair) SessionUtility.getSession(request).getAttribute("keys"); String decryptedPass = JCryptionUtil.decrypt(pass, keys); request.setAttribute("pass", decryptedPass);
到此,就处理了。
现在我不知道,还有没有更好的解决方法。。。。各位大神多指点哈。。
另外:如果自己project 会部署到其他系统(eg:unix.....etc),如果在获取key失败,检查一下server log。如果有securityPermission的exception的话。
请参考
http://hb-keepmoving.iteye.com/blog/1851179
相关推荐
综合网上javasript和java RSA加密解密资源,实现了java和javascript RSA加密解密的互操作,都可以生成公钥传给对方加密然后回传密文用自己的私钥解密。
使用RSA非对称加密完成JavaScript前端RSA加密和分段加解密,最近研究了RSA非对称加密,关于什么是RSA,网上各种文章一搜一大把,但是关于如何使用RSA完成前端的组合加密解密,东西就非常少了,并且由于RSA的特性,一...
注意:AES用的是CryptoJS库的,而RSA则是用的jsencrypt库,RSA用的公钥和私钥是PEM格式的,其他格式无法通过,同时只能支持公钥加密,私钥解密。tips:支持跨语言,支持js与.net后台的加密以及解密,如需借鉴后台...
javascript java rsa 加密 解密 数据加密 数据解密
RSA通过javascript加密java解密
jsencrypt.min.js通过JSEncrypt分段加密解密,自己添加了分段加解密的方法
login.jsp所调用的javascript,有:RSA.jsBigInt.jsBarrett.js博文链接:https://sunxboy.iteye.com/blog/209156
RSA 使用java 和javascript进行加解密
//加密 var encrypt = new JSEncrypt(); encrypt.setPublicKey(PUBLIC_KEY); var encrypted = encrypt.encryptLong("results"); console.log('加密后数据:%o', encrypted); //解密 var decrypt = new JSEncrypt(); ...
RSA非对称 C#解密、js加密实现登陆密文,传输RSA非对称 C#解密、js加密实现登陆密文传输,RSA非对称 C#解密、js加密实现登陆密文传输
参考:Blackberry10 使用js+HTML5开发 RSA加密解密时遇到的问题:BB10端使用js加密与解密, 服务器端使用加密与解密 1,加密非常的简单代码机会上没怎么修改,另外js加密可能出现的问题在BB10 AES加密中已经说过,js ...
本资源是对另一篇资源js端加密,后台解密/JS端解密,后台加密的后台版本,已亲测可用,并且加密和解密都可正常执行,注意:本资源中包含AES加密解密,RSA加密解密,以及生成PEM格式的RSA公私秘钥,但是有点没做好的...
RSA加密解密
这是我有自己的项目中使用的加密解密代码,下载后按说明放到自己的项目中就能使用,如有问题请留言给我,我会第一时间回复大家。
本rsa算法是使用Java与javascript加密解密范例代码,该资料从互联网收集,加上了自己的使用体会,如果对你有帮助那是万幸! js加密部分
在客户端浏览器,Javascript使用RSA算法,以公钥对密码进行加密,服务端使用相应的私钥进行解密。一般用于注册时或登录时填写的密码。 Java引用到的包: commons-lang bouncycastle slf4j commons-codec ...
rsa_javaweb_javascript很简单的前端+后端,使用RSA加密解密,找了网上很多文章,居然没有一个完整的能跑通的例子,只好自己动手写一个。RSA加密的内容长度有限,所以要么是只加密敏感内容,要么是结合其他对称加密...
本rsa算法是使用Java与javascript加密解密范例代码,该资料从互联网收集,加上了自己的使用体会,如果对你有帮助那是万幸!
通过javascript实现RSA加密,使用了标准的国际PKCS1填充,支持UTF-8编码