jsencrypt加密,并解决Message too long for RSA

解决Message too long for RSA报错

在这里我们有两种选择方案,jsencrypt和  encryptlong

使用后者的原因是因为jsencrypt的加密长度有限制,不过encryptlong本身也是有bug,有事又会问题,加密后解析不出来,可能是我的个人原因

这次我主要就说明jsencrypt如果能加密比较长的数据

1、先下载 encrypt

npm i encrypt / yarn add encrypt

2、复制代码

用来给他重新定义一方法使用

加密

const b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
const b64pad = "=";
JSEncrypt.prototype.encryptLong2 = function (string) {
  const k = this.getKey();
  try {
    const lt = "";
    let ct = "";
    //RSA每次加密117bytes,需要辅助方法判断字符串截取位置
    //1.获取字符串截取点
    const bytes = new Array();
    bytes.push(0);
    let byteNo = 0;
    let len, c;
    // eslint-disable-next-line prefer-const
    len = string.length;
    let temp = 0;
    // eslint-disable-next-line no-var
    for (var i = 0; i < len; i++) {
      c = string.charCodeAt(i);
      if (c >= 0x010000 && c <= 0x10FFFF) {
        byteNo += 4;
      } else if (c >= 0x000800 && c <= 0x00FFFF) {
        byteNo += 3;
      } else if (c >= 0x000080 && c <= 0x0007FF) {
        byteNo += 2;
      } else {
        byteNo += 1;
      }
      if ((byteNo % 117) >= 114 || (byteNo % 117) == 0) {
        if (byteNo - temp >= 114) {
          bytes.push(i);
          temp = byteNo;
        }
      }
    }
    //2.截取字符串并分段加密
    if (bytes.length > 1) {
      // eslint-disable-next-line no-var
      for (var i = 0; i < bytes.length - 1; i++) {
        // eslint-disable-next-line no-var
        var str;
        if (i == 0) {
          str = string.substring(0, bytes[i + 1] + 1);
        } else {
          str = string.substring(bytes[i] + 1, bytes[i + 1] + 1);
        }
        const t1 = k.encrypt(str);
        ct += addPreZero(t1, 256);
      }
      ;
      if (bytes[bytes.length - 1] != string.length - 1) {
        const lastStr = string.substring(bytes[bytes.length - 1] + 1);
        const rsaStr = k.encrypt(lastStr)
        ct += addPreZero(rsaStr, 256);
      }
      //console.log("加密完的数据:"+ct);
      return hex2b64(ct);
    }
    const t = k.encrypt(string);
    const y = hex2b64(t);
    return y;
  } catch (ex) {
    return false;
  }
}

解密,(注:前端基本用不着就不用引了)

JSEncrypt.prototype.decryptLong2 = function (string) {
  const k = this.getKey();
  // var maxLength = ((k.n.bitLength()+7)>>3);
  const MAX_DECRYPT_BLOCK = 128;
  try {
    let ct = "";
    let t1;
    let bufTmp;
    let hexTmp;
    const str = b64tohex(string);
    const buf = hexToBytes(str);
    const inputLen = buf.length;
    //开始长度
    let offSet = 0;
    //结束长度
    let endOffSet = MAX_DECRYPT_BLOCK;

    //分段解密
    console.log(inputLen + "----" + offSet)
    while (inputLen - offSet > 0) {
      if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
        bufTmp = buf.slice(offSet, endOffSet);
        hexTmp = bytesToHex(bufTmp);
        t1 = k.decrypt(hexTmp);
        ct += t1;

      } else {
        bufTmp = buf.slice(offSet, inputLen);
        hexTmp = bytesToHex(bufTmp);
        t1 = k.decrypt(hexTmp);
        ct += t1;

      }
      offSet += MAX_DECRYPT_BLOCK;
      endOffSet += MAX_DECRYPT_BLOCK;
    }
    return ct;
  } catch (ex) {
    return false;
  }
}

3、需要引入的方法

这些都是编码过程中需要使用的一些方法

//  在JsEncrypt原型上写了分段加密方法 encryptLong 使用时替换encrypt方法即可
function hex2b64(h) {
  let i;
  let c;
  let ret = "";
  for (i = 0; i + 3 <= h.length; i += 3) {
    c = parseInt(h.substring(i, i + 3), 16);
    ret += b64map.charAt(c >> 6) + b64map.charAt(c & 63);
  }
  if (i + 1 == h.length) {
    c = parseInt(h.substring(i, i + 1), 16);
    ret += b64map.charAt(c << 2);
  }
  else if (i + 2 == h.length) {
    c = parseInt(h.substring(i, i + 2), 16);
    ret += b64map.charAt(c >> 2) + b64map.charAt((c & 3) << 4);
  }
  while ((ret.length & 3) > 0) ret += b64pad;
  return ret;
}
function hexToBytes(hex: string) {
  for (var bytes = [], c = 0; c < hex.length; c += 2)
    bytes.push(parseInt(hex.substr(c, 2), 16));
  return bytes;
}
function bytesToHex(bytes: string | any[]) {
  for (var hex = [], i = 0; i < bytes.length; i++) {
    hex.push((bytes[i] >>> 4).toString(16));
    hex.push((bytes[i] & 0xF).toString(16));
  }
  return hex.join("");
}
function b64tohex(str: string) {
  for (var i = 0, bin = atob(str.replace(/[ \r\n]+$/, "")), hex = []; i < bin.length; ++i) {
    var tmp = bin.charCodeAt(i).toString(16);
    if (tmp.length === 1) tmp = "0" + tmp;
    hex[hex.length] = tmp;
  }
  return hex.join("");
}
function addPreZero(num, length) {
  var t = (num + '').length,
    s = '';
  for (var i = 0; i < length - t; i++) {
    s += '0';
  }

  return s + num;
}

 三、代码中使用

尽可能两个都设置,这个是我封装的方法

const encryptLong = (Encstr: string) => {
  const encrypt = new JSEncrypt();
  encrypt.setPublicKey(PUBLIC_KEY);       // 你的公钥
  encrypt.setPrivateKey(PRIVATE_KEY)      // 你的私钥
  const data = encrypt.encryptLong2(Encstr);
  return data;
}

使用过程

const data = {
  "id": "7ca6a4981a28cf3734343434242710c2c",
  "name": "admin",
  "userName": "admin",
  "phone": "13211222222222",
  "sex": 0,
  "roleId": "32423asdsad4234234",
  "isDriver": 0,
  "department": "体育部",
  "status": 0,
  "reset": 1,
  "remark": "你好呀你是哪里人呢",
  "companyId": "060b8b4fd3ef48f589727db415571427"
}
const strJSON= JSON.stringify(data);   // 将jso转为字符串
const result = encryptLong(strJSON);    // 调用封装的方法

//加密结果 后端也要使用分段解密

ZHOd7cj0zc0Iaw1hqOH4TFGLxhWGpaqPqWQ+jTVUnosAPr85LAuFXRxZpD6czT0eh96XhRxWgZIQxsqkXEaOPKk1LKWHahrkf1IvtyBO1Uf8GEVkGMPcqj27Qx/HfrsZaUoV0awXVP7dcu/4HDLyF50Is1H7VmUULWmCHd1xxJpvTS5B8yptitanEqDL8pf0qx1dF7AHLNojYw9xusBfWCp21BOyrzjprKtW2ZRQeRmmxURRpPtqoJdOU0PwI/ZbPTtwK26nlLwlzIOkqz5wx9qyjm7ub38sulZP2BGZfv+3EjatVS7XqzxmvcQLPwIU/adoUVFg74XZbg6UGpYi0EXZkqVz03JaG190PxwdjN6ds0gU9WTvSPZAxd7ce7M+LjE/SwP6czAePgG9kHmD3KXJTJ8Ja8PtZUPDnw2Ar8LJL7oyDrTAVLO+IbozO6YMXkVgeZytJ4TwZBfHcSDECfpp+ge1atHtukgKz3Q2O3IO2AN6Cm6zQHTRv...


基本上就是如此使用

完美使用,完结撒花

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值