【问题标题】:Nodejs crypto.getHashes() returns an empty arrayNodejs crypto.getHashes() 返回一个空数组
【发布时间】:2020-01-27 05:42:34
【问题描述】:

我在使用exceljs' sheet protection 功能时遇到错误–Error: Hash algorithm 'sha512' not supported!。在查看了它的源文件后,我发现了错误的原因:crypto.getHashes() 正在返回一个空数组。我似乎找不到解决方案,也找不到空数组的原因,有什么想法吗?

节点 v11.2.0

ExcelJSv3.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 lib - 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');
  }

如果有人需要更多说明,请随时在下方发表评论。

任何帮助将不胜感激。

【问题讨论】:

  • 请提供更多信息,例如您编写的代码。

标签: javascript node.js typescript exceljs


【解决方案1】:

有一个bug on an unrelated project 表明crypto.getHashes 可以在数组原型已被修改的情况下返回一个空数组。在错误报告中,这是由于使用了collections.js

通过您自己的代码或通过在crypto 模块之前导入的第三方模块修改数组原型,可能会导致crypto.getHashes 返回一个空数组。

【讨论】:

    猜你喜欢
    • 2012-12-20
    • 2021-12-27
    • 2011-10-10
    • 2021-11-18
    • 1970-01-01
    相关资源
    最近更新 更多