Node.js使用crypto/cipher加密文件报Invalid key length问题求助
问题根因
你使用的是AES-256加密算法,要求密钥必须是准确的32字节长度,报错的直接原因就是你独立调用encryptFile时传入的密钥长度不符合要求。
在encryptFolder方法中你对原始输入的密钥做了两步处理:
- 先把原始密钥字符串反转后转base64
- 再通过
crypto.pbkdf2Sync方法衍生出固定32字节长度的密钥Buffer,这时候传给encryptFile的密钥完全符合AES-256的要求,所以不会报错。
而你独立调用encryptFile时直接传入了原始字符串,没有经过上述衍生处理,密钥长度不符合要求,自然抛出非法密钥长度的错误。
解决方法
把密钥衍生的逻辑抽成公共工具函数,不管是从encryptFolder调用还是独立调用encryptFile,都先对原始密钥做统一衍生处理后再传入。
步骤1:抽离公共密钥衍生函数
const crypto = require('crypto'); function deriveRawKey(rawKey) { // 保留你原有处理逻辑 const reversedKey = rawKey.split('').reverse().join(''); const base64Key = Buffer.from(reversedKey).toString('base64'); const fixedSalt = Buffer.from('ba6dfaa9a6db69f0f2d50745a3516f1cb080e637ceadea4f5e6d9edff3c079602130694585e1df1a3a3176b20fcd10b0af87f6dc766fafd26b0928e7c49ebcdf', 'hex'); // 衍生出32字节长度的AES-256密钥 return crypto.pbkdf2Sync(base64Key, fixedSalt, 2145, 32, 'sha512'); }
步骤2:修改encryptFolder调用逻辑
把原来encryptFolder里的密钥处理逻辑替换成调用公共函数即可:
async function encryptFolder(path, key, maxFileSize = 0) { return new Promise(async (resolve, reject) => { // 替换原有密钥处理逻辑 const processedKey = deriveRawKey(key); var files = await recursive(path, ["node_modules", "*.enc"]); var promises = [] for (let i = 0; i < files.length; i++) { var file = files[i]; if (maxFileSize != 0) if (((fs.statSync(file).size) / 1000000.0) > maxFileSize) continue // 传入处理后的密钥 promises.push(encryptFile(file, processedKey)); } Promise.all(promises).then(() => { resolve() }).catch((err) => { if (err) { reject(err); } }); }) }
步骤3:独立调用时先处理密钥
之后单独调用encryptFile时,先把你输入的原始密码传入deriveRawKey处理后再传入即可:
// 示例:独立调用加密单个文件 const rawUserKey = "你设置的加密密码"; const processedKey = deriveRawKey(rawUserKey); encryptFile("要加密的文件路径", processedKey) .then(() => console.log("加密成功")) .catch(err => console.error("加密失败", err));
额外安全建议
当前你把盐值硬编码在代码中,安全性较低。实际使用时建议为每个加密文件生成随机盐,将盐值存储在加密文件的头部,解密时从文件头读取盐再衍生密钥,可大幅提升加密安全性。
内容的提问来源于stack exchange,提问作者Aditya Jha
相关产品推荐
相关产品推荐

