RSA分段加密解密

2,041 阅读2分钟
  最近有一个需求,需要前端把传参整体加密,然后由后端解密,对比传参数据,防止数据篡改.
  使用 RSA 非对称加密,前端公钥加密,后端私钥解密

遇到的问题

   之前前端都是用 jsencrypt.js 进行加密,但是有一个问题,
   这个加密方法对数据长度有限制,超过100个字符加密就会报错,而我们传参的参数不可能都控制在100个字符内.
   之后发现了另外一个js工具 encryptjs,可以加密超长的数据

encryptjs 的使用

encryptjs 文档地址

npm install encryptjs --save-dev
 var encrypt=require('encryptjs');

调用 encryptLong() 方法加密

后端处理

  后台调用正常解密方法发现解密失败了,因为encryptLong加密实际上是分段加密,后端同样也要分段解密
  

后端分段解密代码


public  String privateKeyDecrypt(String content)
        throws Exception {
    //调用Java加密的Cipher对象,
    Cipher cipher = Cipher.getInstance("RSA");
    cipher.init(Cipher.DECRYPT_MODE,privateKey);//第一个参数表示这是加密模式,第二个参数表示私钥密钥


    byte[] bytesContent = Base64.getDecoder().decode(content.getBytes());
    int inputLen = bytesContent.length;
    int offLen = 0;
    int i = 0;
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    while(inputLen - offLen > 0){
        byte[] cache;
        if(inputLen - offLen > 128){
            cache = cipher.doFinal(bytesContent,offLen,128);
        }else{
            cache = cipher.doFinal(bytesContent,offLen,inputLen - offLen);
        }
        byteArrayOutputStream.write(cache);
        i++;
        offLen = 128 * i;

    }
    byteArrayOutputStream.close();
    byte[] byteArray = byteArrayOutputStream.toByteArray();

    //使用Base64对加密结果进行编码
    return new String(byteArray);
}

每次通过128字节循环解密

这个时候又有一个新的问题,发现参数没有中文可以解密成功,有中文就会解密失败

这个问题最后通过在前端加密前先使用 encodeURIComponent() 方法对字符串转码在加密
后端解密后同样转码解决

转码的问题

使用 JDK 自带的 URLDecoder.decode() 方法解密原字符串,有空格的话空格会转成+号
推荐使用 springboot 提供的 UriUtils.decode() 方法不会有这个问题.