java web使用jsencrypt.js做RSA加密(一)

1 背景

在登录页面存在明文传输的漏洞,为了解决这个问题百度到了两种方案,第一种是使用https协议,许多人都推荐这种方案。第二种是对传输的信息使用加密算法进行加密然后传输。

最后选择了第二种方案,原因是第一种的证书需要申请并且需要花钱,有免费证书有很多但大多有效期是一年。但网上评价https确实好,个人感觉https还是首选,借用网友一句话“没有https的都是在裸奔”。

本文并不涉及https的相关内容,只是前端使用了jsencrypt.js,结合后端代码做了RSA加密。

2 代码

2.1准备jar和js

接下来的RSAUtils工具类需要导入commons-codec-1.10.jar,前端需要jsencrypt.js。以上传到SCDN下载,不需要积分,编写本章时在审核。百度云链接稍后发出。

2.2 工具类

建立一个工具类RSAUtils,这个类借鉴了网友的代码,出处我忘记保存了。

使用这个类的initKey()方法生成密钥对,getPublicKey()方法可以得到公钥字符串,将其传输到前端中用于信息加密。

public class RSAUtils {

    private static final String KEYALGORITHM = "RSA";
 
    private static final String PUBLICKEY = "RSAPublicKey";
    private static final String PRIVATEKEY = "RSAPrivateKey";
 
    //rsa私钥  或者可从配置文件读取。
//    public static final String DECRYPTPRIVATEKEY = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAIMzJa4oZpQcPhRDTIaWnF4olSaeGt5oV0XFwoeeSK+FZ3lc4N34523tdfasgba";
 
    private RSAUtils(){super();}
 
    public static byte[] decryptBASE64(String key) {
        Base64 base64 = new Base64();
        return base64.decode(key);
    }
 
    public static String encryptBASE64(byte[] bytes) {
        Base64 base64 = new Base64();
        return base64.encodeToString(bytes);
    }
 


 
    public static byte[] decryptByPrivateKey(byte[] data, String key){
        try {
 
            byte[] keyBytes = decryptBASE64(key);
 
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEYALGORITHM);
            Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            return cipher.doFinal(data);
        }catch (Exception e){
//            log.error("RSAUtilsPrivateKeyDecryptError");
        	e.printStackTrace();
            return new byte[0];
        }
    }
 
    /**
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPrivateKey(String data, String key){
        return decryptByPrivateKey(decryptBASE64(data), key);
    }
 
    /**
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] decryptByPublicKey(byte[] data, String key){
        try {
 
            byte[] keyBytes = decryptBASE64(key);
 
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEYALGORITHM);
            Key publicKey = keyFactory.generatePublic(x509KeySpec);
 
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            return cipher.doFinal(data);
        }catch (Exception e){
//            log.error("RSAUtilsPublicKeyDecryptError");
        	e.printStackTrace();
            return new byte[0];
        }
 
    }
 
    /**
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPublicKey(String data, String key) {
        try {
 
            byte[] keyBytes = decryptBASE64(key);
 
            X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEYALGORITHM);
            Key publicKey = keyFactory.generatePublic(x509KeySpec);
 
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            return cipher.doFinal(data.getBytes());
        }catch (Exception e){
//            log.error("RSAUtilsPublicKeyEncryptError");
        	e.printStackTrace();
            return new byte[0];
        }
    }
 
    /**
     *
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static byte[] encryptByPrivateKey(byte[] data, String key){
        try {
 
            byte[] keyBytes = decryptBASE64(key);
 
            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEYALGORITHM);
            Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
 
            Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            return cipher.doFinal(data);
        }catch (Exception e){
//            log.error("RSAUtilsPrivateKeyEncryptError");
        	e.printStackTrace();
            return new byte[0];
        }
    }
 
    /**
     *
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPrivateKey(Map<String, Key> keyMap){
        if(keyMap != null){
            Key key = keyMap.get(PRIVATEKEY);
            return encryptBASE64(key.getEncoded());
        }else{
            return "";
        }
    }
 
    /**
     *
     * @param keyMap
     * @return
     * @throws Exception
     */
    public static String getPublicKey(Map<String, Key> keyMap){
        if(keyMap != null){
            Key key = keyMap.get(PUBLICKEY);
            return encryptBASE64(key.getEncoded());
        }else {
            return "";
        }
    }
 
    /**
     *
     * @return
     * @throws Exception
     */
    public static Map<String, Key> initKey(){
        try {
            KeyPairGenerator keyPairGen = KeyPairGenerator
                    .getInstance(KEYALGORITHM);
            keyPairGen.initialize(2048);
            KeyPair keyPair = keyPairGen.generateKeyPair();
            Map<String, Key> keyMap = new HashMap(2);
            keyMap.put(PUBLICKEY, keyPair.getPublic());
            keyMap.put(PRIVATEKEY, keyPair.getPrivate());
            return keyMap;
        } catch (NoSuchAlgorithmException e) {
//            log.error("RSAUtilsInitKeyError");
        	e.printStackTrace();
            return null;
        }
    }


}

2.3 前端请求公钥

2.3.1 后端java代码

这里采用了最简单的session存储密钥对。每次回话都生成新的密钥对,加强对信息的保护。将公钥暴露给前端。

PrintWriter out = response.getWriter();

String generateKeypair = request.getParameter("generateKeypair");
		
HttpSession session = request.getSession();
Map<String, Key> keyMap = (Map<String, Key>) session.getAttribute("keyMap");

if (keyMap == null) {
	keyMap = RSAUtils.initKey();
	session.setAttribute("keyMap", keyMap);
}
String puk = RSAUtils.getPublicKey(keyMap);
		
out.println(puk);

2.3.2 前端js代码

先引入jsencrypt.js,在js中得到公钥,然后对数据进行加密。下面代码中contentEncrypted 变量就是加密之后的字符串。

$.ajax({
	type : 'post',
	url : 'url',
	data : {
		"generateKeypair" : true
		},
	success : function(result) {
		//验证成功
		PUBLIC_KEY  = result
        var encrypt = new JSEncrypt();
		encrypt.setPublicKey(PUBLIC_KEY);
        var contentEncrypted = encrypt.encrypt(content)
	}
});

2.4 后端代码解密。

前端将加密之后的信息传递到后端进行解密。附上后端代码,其中decryptContent 就是解密之后的字符串。

Map<String, Key> keyMap = (Map<String, Key>) session.getAttribute("keyMap");
content = URLDecoder.decode(content,"UTF-8").replace(' ', '+');
String DECRYPTPRIVATEKEY = RSAUtils.getPrivateKey(keyMap);
byte[] decryptData = RSAUtils.decryptByPrivateKey(content, DECRYPTPRIVATEKEY);
String decryptContent = new String(decryptData);

这段代码有一点问题,中文解密出来会乱码,会不会和第二行有关,前端的pageEncoding="UTF-8",有没有大佬知道原因。

3 总结

私以为,上面的文字已经说得很清楚了,讲述了一点在java web中使用RSA进行数据加密的过程,其他的可以根据业务需求进行变化,本身还有很大的提升空间,所以本文的题目最后加了个“(一)”,在以后的学习中如果能再进一步,争取写个"(二)",欢迎各位指出不足。

 

 

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值