Node.js 加密与 crypto:哈希、签名与密钥物料
业务里「加密」一词常被混用:有人指 HTTPS,有人指 密码存库,还有人指 接口签名校验。Node 的
crypto模块把好几类能力放在同一个屋檐下。
这一篇想先把 概念边界 划清:哈希、对称加密、非对称加密、签名、随机数 各解决什么问题,以及在 Node 里 默认该用哪些 API、哪些坑和版本有关。
哈希(digest):完整性校验,不是加密
哈希函数(如 SHA-256)把任意长度输入变成 固定长度摘要:
- 单向:从摘要推不回原文(在密码学假设下);
- 用途:校验文件是否被改、内容寻址、配合 HMAC 做 带密钥的完整性。
在 Node 里常见写法是 createHash / hash.update / hash.digest,或 crypto.hash(较新 API,以当前文档为准)。
注意:
- MD5 / SHA-1 已不适合安全场景,仅遗留兼容;
- 密码存储不要只用裸 SHA-256,要用 专用慢哈希(如
scrypt、argon2等——crypto.scrypt是内置选项之一)。
HMAC:共享密钥下的「认证 + 完整性」
HMAC 在哈希里混入 对称密钥,用于:
- Webhook 签名、API 请求签名;
- 验证「只有持有同一密钥的一方才能生成相同 MAC」。
和「加密」的差别:
- HMAC 不隐藏内容,只证明 未被篡改且来自密钥持有者(在密钥不泄露前提下)。
对称加密(AES 等):同一密钥加解密
对称加密适合 大量数据:加解密用 同一个密钥。
实践要点:
- 算法 + 模式 + 填充 要选现代默认(如 AES-GCM 提供 机密性 + 完整性);
- IV / nonce 必须每次随机且与密文一起存储或传输(具体规则随算法而定);
- 密钥来自 环境变量或 KMS,不要写进仓库。
实现上常用 createCipheriv / createDecipheriv(名称以文档为准),避免误用已废弃的「只传密码字符串」式 API。
非对称:公钥加密、私钥签名
RSA / ECDSA 等:
- 公钥加密,私钥解密——适合 密钥交换、小数据;
- 私钥签名,公钥验签——适合 JWT、软件发布、TLS 证书链。
Node 里涉及 PEM / DER、KeyObject、sign / verify。常见坑:
- padding 模式(RSA-OAEP vs PKCS#1)与服务端不一致就验不过;
- 把私钥当字符串到处传——权限与日志里都要收紧。
随机数:randomBytes 与 Math.random
密码学安全随机 用 crypto.randomBytes(或 randomInt 等),不要用 Math.random。
用途:
- session id、CSRF token、nonce、盐值。
小结:先问目标,再选工具
- 只要「指纹」:哈希;要 防篡改且双方有共享密钥:HMAC;
- 要藏内容且单方持有密钥:对称加密(注意 IV 与认证);
- 要身份不可否认或公钥体系:非对称签名 / 验签;
- 所有密钥与随机数 走
crypto与 安全存储,不要自创「混淆算法」。
把 crypto 按上面几条分类,再去看 HTTPS(TLS 终止在哪)、JWT、对象存储预签名 URL,会知道各自落在哪一层。