Nodejs crypto.getHashes() returns 一个空数组
Nodejs crypto.getHashes() returns an empty array
我在使用 exceljs' sheet protection 功能时遇到错误 – Error: Hash algorithm 'sha512' not supported!
。查看它的源文件后,我发现了错误的原因:crypto.getHashes()
正在返回一个空数组。我似乎找不到解决方案,也找不到空数组的原因,有什么想法吗?
节点 v11.2.0
ExcelJS v3.6.0
src/routes/export-excel/customer.ts
import ExcelJS from "exceljs";
const workbook = new ExcelJS.Workbook();
// workbook config
workbook.eachSheet(async (worksheet, sheetId) => {
worksheet.eachRow((row, rowNumber) => {
row.eachCell((cell, colNumber) => {
switch (exportCols.getCodes()[colNumber - 1]) {
// other case statements
case "date_created":
case "date_modified":
cell.protection = { locked: false }; // locks the cells under the date created & modified columns
break;
}
})
await worksheet.protect("passWord123", {
selectLockedCells: false,
formatCells: true,
insertRows: true,
// other config props
});
})
})
exceljs lib - 保护方法的定义
node_modules/exceljs/lib/utils/worksheet.js Worksheet.protect
// Worksheet Protection
protect(password, options) {
// TODO: make this function truly async
// perhaps marshal to worker thread or something
return new Promise(resolve => {
this.sheetProtection = {
sheet: true,
};
if (password) {
this.sheetProtection.algorithmName = 'SHA-512';
this.sheetProtection.saltValue = Encryptor.randomBytes(16).toString('base64');
this.sheetProtection.spinCount = 100000;
this.sheetProtection.hashValue = Encryptor.convertPasswordToHash(password, 'SHA512', this.sheetProtection.saltValue, this.sheetProtection.spinCount);
}
if (options) {
this.sheetProtection = Object.assign(this.sheetProtection, options);
}
resolve();
});
}
exceljs 库 - convertPasswordToHash 方法的定义
node_modules/exceljs/lib/utils/encryptor.js Encryptor.convertPasswordToHash
convertPasswordToHash(password, hashAlgorithm, saltValue, spinCount) {
hashAlgorithm = hashAlgorithm.toLowerCase();
const hashes = crypto.getHashes();
console.log("supported hashes", hashes) // <== hashes was empty w/c caused the 'Hash algorithm '${hashAlgorithm}' not supported!' error to be thrown
if (hashes.indexOf(hashAlgorithm) < 0) {
throw new Error(`Hash algorithm '${hashAlgorithm}' not supported!`);
}
// Password must be in unicode buffer
const passwordBuffer = Buffer.from(password, 'utf16le');
// Generate the initial hash
let key = this.hash(
hashAlgorithm,
Buffer.from(saltValue, 'base64'),
passwordBuffer
);
// Now regenerate until spin count
for (let i = 0; i < spinCount; i++) {
const iterator = Buffer.alloc(4);
// this is the 'special' element of Excel password hashing
// that stops us from using crypto.pbkdf2()
iterator.writeUInt32LE(i, 0);
key = this.hash(hashAlgorithm, key, iterator);
}
return key.toString('base64');
}
如果有人需要更多说明,请不要犹豫,在下方发表评论。
如有任何帮助,我们将不胜感激。
有个bug on an unrelated project that suggests crypto.getHashes
can return an empty array if the array prototype has been modified. In the bug report, it was due to the use of collections.js.
通过您自己的代码或在 crypto
模块之前导入的第三方模块修改数组原型,可能导致 crypto.getHashes
到 return 一个空数组。
我在使用 exceljs' sheet protection 功能时遇到错误 – Error: Hash algorithm 'sha512' not supported!
。查看它的源文件后,我发现了错误的原因:crypto.getHashes()
正在返回一个空数组。我似乎找不到解决方案,也找不到空数组的原因,有什么想法吗?
节点 v11.2.0
ExcelJS v3.6.0
src/routes/export-excel/customer.ts
import ExcelJS from "exceljs";
const workbook = new ExcelJS.Workbook();
// workbook config
workbook.eachSheet(async (worksheet, sheetId) => {
worksheet.eachRow((row, rowNumber) => {
row.eachCell((cell, colNumber) => {
switch (exportCols.getCodes()[colNumber - 1]) {
// other case statements
case "date_created":
case "date_modified":
cell.protection = { locked: false }; // locks the cells under the date created & modified columns
break;
}
})
await worksheet.protect("passWord123", {
selectLockedCells: false,
formatCells: true,
insertRows: true,
// other config props
});
})
})
exceljs lib - 保护方法的定义
node_modules/exceljs/lib/utils/worksheet.js Worksheet.protect
// Worksheet Protection
protect(password, options) {
// TODO: make this function truly async
// perhaps marshal to worker thread or something
return new Promise(resolve => {
this.sheetProtection = {
sheet: true,
};
if (password) {
this.sheetProtection.algorithmName = 'SHA-512';
this.sheetProtection.saltValue = Encryptor.randomBytes(16).toString('base64');
this.sheetProtection.spinCount = 100000;
this.sheetProtection.hashValue = Encryptor.convertPasswordToHash(password, 'SHA512', this.sheetProtection.saltValue, this.sheetProtection.spinCount);
}
if (options) {
this.sheetProtection = Object.assign(this.sheetProtection, options);
}
resolve();
});
}
exceljs 库 - convertPasswordToHash 方法的定义
node_modules/exceljs/lib/utils/encryptor.js Encryptor.convertPasswordToHash
convertPasswordToHash(password, hashAlgorithm, saltValue, spinCount) {
hashAlgorithm = hashAlgorithm.toLowerCase();
const hashes = crypto.getHashes();
console.log("supported hashes", hashes) // <== hashes was empty w/c caused the 'Hash algorithm '${hashAlgorithm}' not supported!' error to be thrown
if (hashes.indexOf(hashAlgorithm) < 0) {
throw new Error(`Hash algorithm '${hashAlgorithm}' not supported!`);
}
// Password must be in unicode buffer
const passwordBuffer = Buffer.from(password, 'utf16le');
// Generate the initial hash
let key = this.hash(
hashAlgorithm,
Buffer.from(saltValue, 'base64'),
passwordBuffer
);
// Now regenerate until spin count
for (let i = 0; i < spinCount; i++) {
const iterator = Buffer.alloc(4);
// this is the 'special' element of Excel password hashing
// that stops us from using crypto.pbkdf2()
iterator.writeUInt32LE(i, 0);
key = this.hash(hashAlgorithm, key, iterator);
}
return key.toString('base64');
}
如果有人需要更多说明,请不要犹豫,在下方发表评论。
如有任何帮助,我们将不胜感激。
有个bug on an unrelated project that suggests crypto.getHashes
can return an empty array if the array prototype has been modified. In the bug report, it was due to the use of collections.js.
通过您自己的代码或在 crypto
模块之前导入的第三方模块修改数组原型,可能导致 crypto.getHashes
到 return 一个空数组。