前几天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
相关推荐
这个库很可能提供了对RSA加密的基本操作,如生成公钥/私钥对,使用公钥加密数据,以及使用私钥解密数据。开发者可以利用这个库将大文件或长字符串通过分段加密的方式进行安全传输。 在实际应用中,前端开发者首先...
在这个项目"Java RSA加密前后端实现"中,前端部分可能使用JavaScript实现了RSA加密。JavaScript作为客户端语言,可以方便地在用户浏览器中运行,对用户的密码或其他敏感信息进行加密,然后将加密后的数据发送到...
后端则可能使用Java的Java Cryptography Extension (JCE)、Python的pycryptodome库或者其他语言的相应库来处理RSA加密解密。 在"RSA_DEMO"这个压缩包文件中,可能包含了实现RSA加密交互的示例代码,包括生成密钥对...
本文将详细介绍一个实际案例:如何在前端使用JavaScript库`jsencrypt`进行RSA加密,并在后端使用Java进行解密。这个功能实现的核心知识点包括RSA算法、`jsencrypt`库的使用以及前后端的交互。 首先,RSA是一种非...
这些文件对于理解并实现RSA加密解密的具体步骤至关重要。 总之,RSA加密技术为Web应用提供了安全的数据传输手段,确保了用户数据在互联网上的隐私和安全。在实际开发中,我们需要根据项目的具体需求,合理选择密钥...
在前端,可以使用`jsencrypt`库进行RSA加密,后端使用Java的`java.security`包中的`RSAPublicKey`和`RSAPrivateKey`进行解密。 **JavaScript加密实现** 在前端,`jsencrypt.js`库提供了RSA加密功能,可以方便地将...
在你的项目中,前端(JavaScript)和后端(Java)都实现了RSA加密,使得数据在传输过程中更加安全。 在JavaScript中,你可以使用`crypto-js`库来实现RSA加密。这个库提供了各种加密算法,包括RSA。首先,你需要生成...
总之,这个项目展示了如何在Java和JavaScript之间实现RSA加密解密的互操作,这对于需要在服务器端和客户端之间安全交换敏感数据的场景非常有用。它依赖于对RSA加密算法的深入理解和对不同编程语言加密库的熟练应用。...
实际应用中,通常会结合对称加密算法(如AES)来提高效率,即使用RSA加密对称密钥,然后用此密钥加密大量数据。 在项目实践中,还需要考虑兼容性问题,因为不同库可能对密钥格式或加密参数有不同的要求。例如,...
在这个"RSA 前端加密C#后端解密"的程序中,前端使用JavaScript进行RSA加密,而后端使用C#进行解密。这是一个常见的应用场景,因为前端通常不保存敏感的私钥,而将加密后的数据发送到服务器进行安全处理。 ...
后端,Java作为一种常用的企业级开发语言,拥有丰富的安全库,例如Bouncy Castle,用于处理RSA加密解密。Java代码可能使用了`java.security`包下的`KeyPairGenerator`、`PublicKey`、`PrivateKey`等类来生成和管理...
RSA加密解密是一种广泛应用于网络安全中的非对称加密算法,由Ron Rivest、Adi Shamir和Leonard Adleman三位科学家在1977年提出,因此得名RSA。这种算法基于大数因子分解的困难性,为数据提供了一种安全的传输方式。 ...
以下是使用RSA加密解密的基本步骤: 1. **密钥生成**:在服务器端,使用`KeyPairGenerator`生成一对RSA密钥,包括公钥和私钥。公钥通常会被发送给前端,而私钥则保留在服务器上。 2. **前端加密**:前端接收到公钥...
有两个Java文件(RSACrypt.java和RSACryptTest.java)和一个JavaScript文件(jsencrypt.min.js),这表明代码实现了RSA加密解密的Java版本和JavaScript版本,可以在客户端和服务端之间进行安全的数据传输。...
在这个场景中,我们将讨论如何在Django应用中实现RSA加密和解密,以便于前端与后端的安全通信。 首先,让我们理解RSA的基本原理。RSA是一种基于大素数因子分解困难性的公钥加密算法。它包括一对密钥:公钥(可公开...
前端加密可以确保即使数据在传输过程中被截取,攻击者也无法轻易获取原始信息,因为解密需要私钥,而私钥仅保存在服务器端。 前端加密的过程通常是这样的:首先,前端应用(例如JavaScript)使用公钥对用户输入的...
在"rsa加密_js加密_java解密"的场景中,我们首先在前端(通常是浏览器环境)使用JavaScript实现RSA加密。JS库如CryptoJS或Forge提供了RSA加密的功能,可以将待保护的数据转化为密文。这个过程可能涉及将数据分割成...
在Web开发中,由于浏览器端不支持Java,而JavaScript则可以在客户端运行,因此,使用RSA在Java后端生成密钥对,并将公钥传递给JavaScript前端进行加密,再将加密后的数据发送回服务器,由Java后端使用私钥解密,是...
通过分析和学习这些代码,开发者可以更好地理解RSA加密解密的过程,并将其应用于自己的项目中。 为了实现跨语言的加密解密,确保两端使用的密钥格式一致至关重要。例如,JavaScript中通常使用Base64编码的密钥字符...