前几天user有个要求,就是系统中所有的密码输入框的内容(password) 必须加密提交。即使用工具能抓取到request,但是抓取到的password 都是密文。
非对称加密。 密钥不是一个,而是一对,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:
- 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的话。
请参考
相关推荐
综合网上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编码