JSEncrypt长文本分段加解密 解决长字符串加解密失败

github: https://github.com/zhangwen9229/jsencrypt
修改源码解决方案:

   //文件路径 src/JSEncrypt.ts,增加以下方法
   // 分段加密长字符串
   public encryptLong(str:string) {
       try {
           return hex2b64(this.getKey().encryptLong(str));
       } catch (ex) {
           return false;
       }
   }
   
   // 分段解密长字符串
   public decryptLong(str:string) {
       try {
           return this.getKey().decryptLong(b64tohex(str));
       } catch (ex) {
           return false;
       }
   }
    //文件路径 lib/jsbn/rsa.ts,增加以下方法
    // 分段加密长字符串
    public encryptLong(text:string) {
        let ct = "";
        // RSA每次加密117bytes,需要辅助方法判断字符串截取位置
        // 1.获取字符串截取点
        const bytes = new Array();
        bytes.push(0);
        let byteNo = 0;
        const len = text.length;
        let c;
        let temp = 0;
        for (let i = 0; i < len; i++) {
            c = text.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) {
            for (let i = 0; i < bytes.length - 1; i++) {
                let str;
                if (i == 0) {
                    str = text.substring(0, bytes[i + 1] + 1);
                } else {
                    str = text.substring(bytes[i] + 1, bytes[i + 1] + 1);
                }
                const t1 = this.encrypt(str);
                ct += t1;
            }
            if (bytes[bytes.length - 1] != text.length - 1) {
                const lastStr = text.substring(bytes[bytes.length - 1] + 1);
                ct += this.encrypt(lastStr);
            }
            return (ct);
        }
        const t = this.encrypt(text);
        return t;
    }

    // 分段解密长字符串
    public decryptLong(text:string) {
        const maxLength = ((this.n.bitLength() + 7) >> 3);
        try {
            if (text.length > maxLength) {
                let ct = "";
                const lt = text.match(/.{1,256}/g);
                lt.forEach((entry) => {
                    const t1 = this.decrypt(entry);
                    ct += t1;
                });
                return ct;
            }
            const y = this.decrypt(text);
            return y;
        } catch (ex) {
            return false;
        }
    }
  • 修改完后,执行gulp打包
  • 注意:该方案长文本解密,中文直接加密会出现乱码(解决方案:可以让后台加密之前,先将字符串encodeURI后再加密,前端解密后,再decodeURIComponent,则可避免该问题)

参考:https://jackiedark.github.io/2018/02/05/JSEncrypt长文本分段加解密/

展示评论