三步实现Node.js文件加密:node-fs-extra与crypto模块的安全实践
你还在为敏感文件暴露风险担忧?本文将通过node-fs-extra与crypto模块,实现一套完整的文件加密/解密方案。读完你将掌握:
- 利用lib/copy/copy.js实现加密后文件安全迁移
- 通过crypto模块构建AES-256加密算法
- 结合lib/json/output-json.js实现加密配置持久化
核心模块准备
项目依赖架构
node-fs-extra提供文件系统增强能力,其核心API封装于lib/index.js,包含:
- 文件操作:copy、remove、mkdirs
- 路径处理:path-exists
- 数据持久化:outputJson
加密算法选型
采用Node.js内置crypto模块的AES-256-CBC模式,特点:
- 对称加密效率高,适合大文件处理
- 16字节IV向量确保相同明文加密结果不同
- 支持流模式处理,避免内存溢出
实现步骤
1. 加密工具函数开发
创建crypto-utils.js实现核心加密逻辑:
const crypto = require('crypto');
const fs = require('fs-extra');
// 加密配置
const CONFIG = {
algorithm: 'aes-256-cbc',
key: crypto.scryptSync('your-32byte-key', 'salt', 32), // 32字节密钥
ivLength: 16
};
// 加密文件
async function encryptFile(srcPath, destPath) {
const iv = crypto.randomBytes(CONFIG.ivLength);
const cipher = crypto.createCipheriv(CONFIG.algorithm, CONFIG.key, iv);
// 确保目标目录存在
await fs.ensureDir(fs.path.dirname(destPath));
const input = fs.createReadStream(srcPath);
const output = fs.createWriteStream(destPath);
// 写入IV向量(前16字节)
output.write(iv);
return new Promise((resolve, reject) => {
input.pipe(cipher).pipe(output)
.on('finish', resolve)
.on('error', reject);
});
}
// 解密文件
async function decryptFile(encryptedPath, destPath) {
const iv = await fs.readFile(encryptedPath, { length: CONFIG.ivLength });
const decipher = crypto.createDecipheriv(CONFIG.algorithm, CONFIG.key, iv);
const input = fs.createReadStream(encryptedPath, { start: CONFIG.ivLength });
const output = fs.createWriteStream(destPath);
return new Promise((resolve, reject) => {
input.pipe(decipher).pipe(output)
.on('finish', resolve)
.on('error', reject);
});
}
module.exports = { encryptFile, decryptFile };
2. 集成文件系统操作
利用lib/copy/copy.js的文件遍历能力,实现加密备份功能:
const { encryptFile } = require('./crypto-utils');
const fs = require('fs-extra');
async function encryptAndBackup(sourceDir, backupDir) {
// 递归读取目录
const entries = await fs.readdir(sourceDir, { withFileTypes: true });
for (const entry of entries) {
const srcPath = `${sourceDir}/${entry.name}`;
const destPath = `${backupDir}/${entry.name}.enc`;
if (entry.isDirectory()) {
await encryptAndBackup(srcPath, destPath); // 递归处理子目录
} else if (entry.isFile()) {
await encryptFile(srcPath, destPath); // 加密文件
console.log(`加密完成: ${destPath}`);
}
}
}
// 使用示例
encryptAndBackup('./sensitive-data', './encrypted-backup')
.then(() => console.log('备份完成'))
.catch(err => console.error('备份失败:', err));
3. 加密配置管理
使用lib/json/output-json.js存储加密元数据:
const fs = require('fs-extra');
const crypto = require('crypto');
async function saveEncryptionMeta(metaPath, fileMap) {
const meta = {
timestamp: new Date().toISOString(),
checksum: crypto.createHash('sha256').update(JSON.stringify(fileMap)).digest('hex'),
files: fileMap
};
await fs.outputJson(metaPath, meta, { spaces: 2 });
}
// 记录加密文件映射关系
saveEncryptionMeta('./encryption-meta.json', {
'user-data.csv': 'user-data.csv.enc',
'config.ini': 'config.ini.enc'
});
安全最佳实践
-
密钥管理
- 生产环境避免硬编码密钥,可使用环境变量或密钥管理服务
- 示例:
process.env.ENCRYPTION_KEY加载密钥
-
完整性校验
结合lib/fs/index.js的readFile实现文件校验:
async function verifyFileIntegrity(filePath, expectedHash) {
const data = await fs.readFile(filePath);
const actualHash = crypto.createHash('sha256').update(data).digest('hex');
return actualHash === expectedHash;
}
- 错误处理
使用lib/util/async.js的异步控制流:
const { asyncIteratorConcurrentProcess } = require('./lib/util/async');
// 并发加密文件(限制5个并发)
async function batchEncrypt(files) {
await asyncIteratorConcurrentProcess(files, async (file) => {
await encryptFile(file.src, file.dest);
}, { concurrency: 5 });
}
应用场景
- 用户数据保护:加密存储用户上传文件
- 配置文件安全:敏感配置通过outputJson加密存储
- 备份加密:结合copy实现加密备份
通过这套方案,可在不影响原有文件操作流程的基础上,无缝集成加密能力,有效降低数据泄露风险。建议定期轮换加密密钥,并通过单元测试验证加密/解密一致性。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



