在 wordArray 到 ByteArray 转换中超出 CryptoJS 最大调用堆栈大小

CryptoJS Maximum Call Stack Size Exceeded in wordArray to ByteArray conversion

我正在尝试使用 CryptoJS 在 React 客户端应用程序中实现加密和解密。加密和解密是可以不出错的,但是只针对小文件的情况。在视频文件 (9MB) 的解密过程中,将 wordArray 转换为 ByteArray 时出现错误 超出最大调用堆栈大小 。处理此转换的代码来自:GitHub

错误: Maximum call stack size exceeded

代码:

 wordArrayToByteArray = (wordArray,length) => {

  if(wordArray.hasOwnProperty("sigBytes") && wordArray.hasOwnProperty("words")){
    length = wordArray.sigBytes;
    wordArray = wordArray.words;
  }

  let result = [];
  let bytes;
  let i = 0;

  while(length > 0){
    bytes = this.wordToByteArray(wordArray[i],Math.min(4,length));
    length -= bytes.length;
    result.push(bytes);
    i++;
  }

  return [].concat.apply([],result);
}

 wordToByteArray = (word, length) => {

  var ba = [],
    i,
    xFF = 0xFF;
  if (length > 0)
    ba.push(word >>> 24);
  if (length > 1)
    ba.push((word >>> 16) & xFF);
  if (length > 2)
    ba.push((word >>> 8) & xFF);
  if (length > 3)
    ba.push(word & xFF);

  return ba;
}

decryptFile = (downloaded) =>{ 
  //convert unit array(encrypted file) to string
  let encryptedString = this.uintToString(downloaded);

  //decrypt and get wordArray
  const decrypted = cryptojs.AES.decrypt(encryptedString,"123");
  console.log(decrypted);

  //convert wordArray to string
  let decryptedString = decrypted.toString(cryptojs.enc.Utf8);


  // form a new word array
  const wordArray = cryptojs.enc.Hex.parse(decryptedString);


  //convert new wordArray to byteArray
  return this.wordArrayToByteArray(wordArray,Object.keys(wordArray).length);
}

uintToString = (uintArray) => {
  const decodedStr = new TextDecoder("utf-8").decode(uintArray);
  return decodedStr;
}

 onDownload = () => {
  ipfs.get(this.state.ipfsHash,(error,files)=>{
    files.forEach((file)=>{
      console.log(file.path);
      const decryptedFile = this.decryptFile(file.content);

      const arrayBufferView = new Uint8Array(decryptedFile);

      const blob = new Blob([arrayBufferView],{type: "video/mp4"});
      console.log(blob);
      fileSaver.saveAs(blob,"curseTheInternet.mp4");
    })
  })
}

或者对客户端加密库的任何其他建议?

问题出在您对 [].concat.apply([], result) 的使用上,如果结果太大,这将导致您看到的错误。据我所知,您正在使用它来展平单词数组。要避免此错误,请尝试使用 .flat

使用这个改进的版本

static wordArrayToByteArray(wordArray: CryptoJS.lib.WordArray, length: number): Uint8Array {
    let words: any = wordArray;
    if (wordArray.hasOwnProperty("sigBytes") && wordArray.hasOwnProperty("words")) {
      length = wordArray.sigBytes;
      words = wordArray.words;
    }

    let result: number[] = [];
    let bytesAdded;
    let i = 0;
    while (length > 0) {
      bytesAdded = this.wordToByteArray(result, words[i], Math.min(4, length));
      length -= bytesAdded.length;
      i++;
    }
    return new Uint8Array(result);
  }

  private static wordToByteArray(result, word, length): number {
    const lengthBefore = result.length;
    const xff = 0xFF;
    if (length > 0)
      result.push(word >>> 24);
    if (length > 1)
      result.push((word >>> 16) & xff);
    if (length > 2)
      result.push((word >>> 8) & xff);
    if (length > 3)
      result.push(word & xff);
    return result.length - lengthBefore;
  }