在 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;
}
我正在尝试使用 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;
}