| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 |
- 'use strict';
- const crypto = require('crypto');
- const Encryptor = {
- /**
- * Calculate a hash of the concatenated buffers with the given algorithm.
- * @param {string} algorithm - The hash algorithm.
- * @returns {Buffer} The hash
- */
- hash(algorithm, ...buffers) {
- const hash = crypto.createHash(algorithm);
- hash.update(Buffer.concat(buffers));
- return hash.digest();
- },
- /**
- * Convert a password into an encryption key
- * @param {string} password - The password
- * @param {string} hashAlgorithm - The hash algoritm
- * @param {string} saltValue - The salt value
- * @param {number} spinCount - The spin count
- * @param {number} keyBits - The length of the key in bits
- * @param {Buffer} blockKey - The block key
- * @returns {Buffer} The encryption key
- */
- convertPasswordToHash(password, hashAlgorithm, saltValue, spinCount) {
- hashAlgorithm = hashAlgorithm.toLowerCase();
- const hashes = crypto.getHashes();
- 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');
- },
- /**
- * Generates cryptographically strong pseudo-random data.
- * @param size The size argument is a number indicating the number of bytes to generate.
- */
- randomBytes(size) {
- return crypto.randomBytes(size);
- },
- };
- module.exports = Encryptor;
|