PASSION之项目运用加密Jcryption

本文介绍了如何在Web前端使用JavaScript的Jcryption库进行RSA加密,以保护用户密码在提交时的安全。当密码输入框失去焦点时,利用获取的服务器端key加密密码,确保即使请求被截获,密码也是密文。服务器端接收到密文后进行解密,实现了前后端的加密通信。
摘要由CSDN通过智能技术生成

前几天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代码:

    需要一个全局变量 var publicKeys;

// 1.获取公钥
function getPublicKey() {
	$.jCryption.getKeys(getPath() + '/service/ajax/encrypt/getkey', function(
			receivedKeys) {
		publicKeys = receivedKeys;
	});
}
// 2.加密密码,如果公钥为空则返回空字符串
function encrypt(password) {
	if ($.trim(password) != "" && "undefined" != publicKeys && null != publicKeys) {
		return $.jCryption.synchronousEncrypt(password, publicKeys);
	} else {
		return "";
	}
}
// 3.获取公钥,同步版
function getPublicKeySync() {
	$.jCryption.getKeysSync(getPath() + '/service/ajax/encrypt/getkey', function(
			receivedKeys) {
		publicKeys = receivedKeys;
	});
}

 Java后端工具类:

package com.taikang.util;

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  创建人 
 * @version V1.0  创建时间:2014-8-7 下午2:52:52 
 */
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);  
	    }  
	  
	    /** 
	     * 用给定的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);  
	        }  
	    }  
	  
	    /** 
	     * 根据RSA密钥解密字符串
	     * @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);  
	        }  
	    }  
	  
	    /** 
	     * 获得密钥模数 
	     *  
	     * @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);  
	    }  
	  
	    /** 
	     * 获得密钥指数 
	     *  
	     * @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;  
	    }  
	  
	  
	    /** 
	     * @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();  
	    }  

	    /** 
	     * @param args 
	     */  
	  public static void main(String[] args) {  
	      JCryptionUtil jCryption;
		try {
			jCryption = new JCryptionUtil();
			System.out.println(jCryption.toPublicKeyString());  
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  
	  }  
}

 

服务器端链接:

/**
	 * 获取加密前台传输字符串用的公钥
	 * @return 公钥的json,包含指数,模数和有效位数
	 * @author 项赢 V1.0 2014-08-08 15:24
	 */
	@RequestMapping("/ajax/encrypt/getkey")
	public @ResponseBody JSONObject getPublicKey(HttpSession session){
		//初始化
		JSONObject keysJson = new JSONObject();
		try {
			LogUtil.info(LogConstants.App,"获取公钥(Get public keys)");
			// 初始化工具类
			JCryptionUtil jCryptionUtil = new JCryptionUtil();
			// 生成密钥
			KeyPair keys = jCryptionUtil.generateKeypair(512);
			// 保存密钥到session
			session.setAttribute("keys", keys);
			// 提取公钥
			String e = JCryptionUtil.getPublicKeyExponent(keys);
			String n = JCryptionUtil.getPublicKeyModulus(keys);
			String md = String.valueOf(JCryptionUtil.getMaxDigits(512));
			LogUtil.info(LogConstants.App,"公钥(Public keys):\ne:" + e + "\nn:" + n + "\nmaxdigits:" + md);
			// 填充返回结果
			keysJson.put("e", e);
			keysJson.put("n", n);
			keysJson.put("maxdigits", md);
		} catch (Exception e){
			e.printStackTrace();
		}
		return keysJson;
	}

	/**
	 * 解密前台传输字符串
	 * @param keys,session中的密钥
	 * @param encryptedPassword,加密过的前台传输字符串
	 * @return 解密完成的字符串,解密出错时返回空串
	 * @author 项赢 V1.0 2014-08-08 16:45
	 */
	public String decrypt(KeyPair keys, String encryptedString){
		String decryptedString = "";
		try {
			LogUtil.info(LogConstants.App,"解密字符串(Decrypt encrypted string)");
			decryptedString = JCryptionUtil.decrypt(encryptedString, keys);
		} catch (Exception e) {
			LogUtil.info(LogConstants.App,"解密字符串时发生异常(Exception on decrypting string)");
			e.printStackTrace();
		}
		return decryptedString;
	}
	

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值