使用JSEncrypt进行分段加密

摘要

近来在项目中给后台传输数据需要进行rsa加密,但是有的数据太长,密钥是2048位的所以只能加密256个字符,于是便想采用分段加密方式进行加密。

问题分析

因为加密的数据里包含中英文,如果从采用charAt来取出每个字符来判断字符算占用的字节实在是太麻烦,所以我才用base64将数据进行编码,这样原始数据就不会包含中文,即可进行简单的长度划分,从而直接去加密。

采用JSEncrypt.js 库进行加密,填充算法库内是pkcs1pad2填充算法

下面是我自己的分段加密方法

JSEncrypt.prototype.encryptLong = function (string) {
        var k = this.getKey();
        var strings = base64.encode(string);
        var encrypArray = new Array();
        try {
          var ct = "";
          if (strings.length > 245) {
            for (var i = 0; i < strings.length; i = i + 245) {
              var str;
              if (strings.length >= (i + 245)) {
                str = strings.substring(i, i + 245);
              } else {
                str = strings.substring(i);
              }
              var t1 = k.encrypt(str);
              encrypArray.push(hex2b64(t1));
            }
            return encrypArray;
          }
          var t = k.encrypt(strings);
          encrypArray.push(hex2b64(t));
          return encrypArray;
        } catch (ex) {
          return false;
        }
      };

我自己的分段解密方法

JSEncrypt.prototype.decryptLong = function (encrypArray) {
        var key = this.getKey();
        try {
          var t3 = "";
          for(var j=0; j < encrypArray.length; j++){
            var t4 = key.decrypt(b64tohex(encrypArray[j]));
            t3 += t4;
          }
          var strings = String(base64.decode(t3));
          return t3;
        } catch (ex) {
          return false;
        }
      };

由于采用JSEncrypt进行加密时其最大加密长度是245,因为需要留出最小11个字节来进行pkcs1pad2填充,所以我才以245的长度来进行数据的截取加密,完成每一段的加密后在调用hex2b64()进行16进制到base64的转化,然后放到数组中去,这样我们便可以得到一个有完整加密数据的数组。

pkcs1pad2填充简单研究

function pkcs1pad2(s,n) {
  if(n < s.length + 11) { // TODO: fix for utf-8
    console.error("Message too long for RSA");
    return null;
  }
  var ba = new Array();
  var i = s.length - 1;
  while(i >= 0 && n > 0) {
    var c = s.charCodeAt(i--);
    if(c < 128) { // encode using utf-8
      ba[--n] = c;
    }
    else if((c > 127) && (c < 2048)) {
      ba[--n] = (c & 63) | 128;
      ba[--n] = (c >> 6) | 192;
    }
    else {
      ba[--n] = (c & 63) | 128;
      ba[--n] = ((c >> 6) & 63) | 128;
      ba[--n] = (c >> 12) | 224;
    }
  }
  ba[--n] = 0;
  var rng = new SecureRandom();
  var x = new Array();
  while(n > 2) { // random non-zero pad
    x[0] = 0;
    while(x[0] == 0) rng.nextBytes(x);
    ba[--n] = x[0];
  }
  ba[--n] = 2;
  ba[--n] = 0;
  return new BigInteger(ba);
}

其中加密完数据以后最少会剩11个字节来进行非零填充,而且填充完的第一位和第二位必然是0,2,第十一位必然是0,想必这就是解密的时候区分哪些是真实数据还是填充数据的依据。

你可能感兴趣的:(使用JSEncrypt进行分段加密)