代码之家  ›  专栏  ›  技术社区  ›  Tachyon

自定义解密:超过最大调用堆栈大小

  •  0
  • Tachyon  · 技术社区  · 7 年前

    发行

    我当前遇到一个问题,出现以下错误: RangeError: Maximum call stack size exceeded 这发生在下面代码部分中概述的行上。

    奇怪的是,当我在较小的数据上调用这个方法时,它的工作没有问题。这个 ApiService 下面提到的解密方法在下面的代码部分有概述,这是专门导致错误的部分。

    希望你们能帮上忙,因为这很奇怪,它只适用于较小的数据量,而不适用于较大的数据量。


    堆栈跟踪

    ERROR Error: Uncaught (in promise): RangeError: Maximum call stack size exceeded
    RangeError: Maximum call stack size exceeded
        at ApiService.<anonymous> (api.service.ts:167)
        at step (tslib.es6.js:97)
        at Object.next (tslib.es6.js:78)
        at fulfilled (tslib.es6.js:68)
        at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391)
        at Object.onInvoke (core.js:17298)
        at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:390)
        at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:150)
        at zone.js:889
        at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
        at resolvePromise (zone.js:831)
        at zone.js:741
        at rejected (tslib.es6.js:69)
        at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:391)
        at Object.onInvoke (core.js:17298)
        at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invoke (zone.js:390)
        at Zone.push../node_modules/zone.js/dist/zone.js.Zone.run (zone.js:150)
        at zone.js:889
        at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
        at Object.onInvokeTask (core.js:17289)
    

    数据

    传递给以下方法的数据如下:

    Data: "PHAl4fGtOUPM9Rop5P0eG1f1L9kx1HQXi5WfZ2jIFakznGLwzl......"
    IV: "AM+Ljm3np1XL+1SiM4IfM+pNx21zQ4q4XnK9DKoN3ZCWKV5CWt62z/myCEZt9e66g/wxC/Jeq1q6yTEaT0AIrwE8ek9OWGWCCFAOttmbYli+SCYzUf3yW0NrcQR3nerpbbXqGjQA4LnNbwm26vQ42AuWhRbK2V7MP0aN4E68NUMGVs+mOjaX6QbZ50wvILSTK0O/y/P2AYiHhXrWPlDajVy8kZ65m4qnPKbDnwzp5lK37fXs9jwwcUUUYW+9jQh4qVkOaQNKvUTZu5BqmDz8/A80B+Q9rt4hy3EdCphWM8bfJ7RE3/W8S/EVUcuElqpsvB6XkBy9Q+VbtjlotZcnnw=="
    Key: "ngOW45g78VaMAAzbWPol9y99lTnjtNylAKstkZF2jWoXq3SQI5Vd+yS2/vNkdtat0BxI+UHKNL98IvvCf3JIYLAfpzFhRjBWCZwo2RZms4OJMwngItPGTFc9cHtSMbTNI5FlXMciJrrA+yj5HWZ3kcpVYn3d8tiXpGEVgEorxdxijhim9vsgXbXS5ZG39KwW2mxOMMiFdd/UbMZLC01zNpE5t8DmYNoMUmCva1Y6cDuZEt8DYM3z4rXLTd2EefnFuX/DcXiD9CKqMyw2bBmIFouv+qDVbnQ/bR5mjLGW/rC7TNELOU2Y/VFf+26wZe2u0C7MRsf9wAbcxPC6UAocAQ=="
    

    代码

    我得到的错误行如下:

    return String.fromCharCode.apply(null, new Uint8Array(decryptedData));
    

    整个抛出错误的方法如下:

    //Method that will decrypt the data being received
    
      private async decryptData(data: any): Promise<any> {
        //Get the client private key from storage
        let clientPrivateKey = localStorage.getItem(AppSettings.PRIVATE_KEY);
    
        //Deserialize the JSON
        let response = data;
    
        //Get the buffer of the IV
        let ivBuffer = this.base64ToArrayBuffer(response.IV);
    
        //Get the private key in CryptoKey format
        let importedPrivateKey = await window.crypto.subtle.importKey(
          "pkcs8",
          this.base64ToArrayBuffer(clientPrivateKey),
          {
            name: "RSA-OAEP",
            hash: { name: "SHA-256" }
          },
          false,
          ["decrypt"]
        );
        //Get the bytes of the IV
        let ivBytes = await window.crypto.subtle.decrypt(
          {
            name: "RSA-OAEP",
          },
          importedPrivateKey,
          ivBuffer
        );
    
        //Take IV to text
        let ivArr = new Uint8Array(ivBytes);
        let IV = this.Utf8ArrayToStr(ivArr);
    
        //Get the buffer of the key
        let keyBuffer = this.base64ToArrayBuffer(response.Key);
        //Decrypt the key
        let keyBytes = await window.crypto.subtle.decrypt(
          {
            name: "RSA-OAEP"
          },
          importedPrivateKey,
          keyBuffer
        );
        //Take the key to text
        let keyArr = new Uint8Array(keyBytes);
        let key = await window.crypto.subtle.importKey(
          "raw", //can be "jwk" or "raw"
          keyArr,
          "AES-CBC",
          false, //whether the key is extractable (i.e. can be used in exportKey)
          ["encrypt", "decrypt"] //can be "encrypt", "decrypt", "wrapKey", or "unwrapKey"
        )
    
        //Take from B64 to bytes then decrypt
        let responseData = this.base64ToArrayBuffer(response.Data);
        //Decrypt the actual data
        //let decryptedData = await this.aes.decrypt(key, IV, responseData);
        let decryptedData = await window.crypto.subtle.decrypt(
          {
            name: "AES-CBC",
            iv: ivArr, //The initialization vector you used to encrypt
          },
          key, //from generateKey or importKey above
          responseData //ArrayBuffer of the data
        )
    
        //Return the decrypted data for use
        return String.fromCharCode.apply(null, new Uint8Array(decryptedData));
      }
    

    Base64助手方法如下所示:

    private arrayBufferToBase64(buffer) {
        var binary = '';
        var bytes = new Uint8Array(buffer);
        var len = bytes.byteLength;
        for (var i = 0; i < len; i++) {
          binary += String.fromCharCode(bytes[i]);
        }
        return window.btoa(binary);
      }
    
      private base64ToArrayBuffer(b64) {
        var byteString = window.atob(b64);
        var byteArray = new Uint8Array(byteString.length);
        for (var i = 0; i < byteString.length; i++) {
          byteArray[i] = byteString.charCodeAt(i);
        }
    
        return byteArray;
      }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Tachyon    7 年前

    我通过改变解码的方式解决了这个问题 ArrayBuffer 一根绳子。

    我替换了以下内容:

    return String.fromCharCode.apply(null, new Uint8Array(decryptedData));
    

    使用:

    return new Uint8Array(decryptedData).reduce(function (data, byte) {
          return data + String.fromCharCode(byte);
        }, '');