Node.js 加密与 crypto:哈希、签名与密钥物料

业务里「加密」一词常被混用:有人指 HTTPS,有人指 密码存库,还有人指 接口签名校验。Node 的 crypto 模块把好几类能力放在同一个屋檐下。
这一篇想先把 概念边界 划清:哈希、对称加密、非对称加密、签名、随机数 各解决什么问题,以及在 Node 里 默认该用哪些 API、哪些坑和版本有关

哈希函数(如 SHA-256)把任意长度输入变成 固定长度摘要

  • 单向:从摘要推不回原文(在密码学假设下);
  • 用途:校验文件是否被改内容寻址、配合 HMAC 做 带密钥的完整性

在 Node 里常见写法是 createHash / hash.update / hash.digest,或 crypto.hash(较新 API,以当前文档为准)。

注意:

  • MD5 / SHA-1 已不适合安全场景,仅遗留兼容;
  • 密码存储不要只用裸 SHA-256,要用 专用慢哈希(如 scryptargon2 等——crypto.scrypt 是内置选项之一)。

HMAC 在哈希里混入 对称密钥,用于:

  • Webhook 签名API 请求签名
  • 验证「只有持有同一密钥的一方才能生成相同 MAC」。

和「加密」的差别:

  • HMAC 不隐藏内容,只证明 未被篡改且来自密钥持有者(在密钥不泄露前提下)。

对称加密适合 大量数据:加解密用 同一个密钥

实践要点:

  • 算法 + 模式 + 填充 要选现代默认(如 AES-GCM 提供 机密性 + 完整性);
  • IV / nonce 必须每次随机且与密文一起存储或传输(具体规则随算法而定);
  • 密钥来自 环境变量或 KMS,不要写进仓库。

实现上常用 createCipheriv / createDecipheriv(名称以文档为准),避免误用已废弃的「只传密码字符串」式 API。

RSA / ECDSA 等:

  • 公钥加密,私钥解密——适合 密钥交换小数据
  • 私钥签名,公钥验签——适合 JWT、软件发布、TLS 证书链

Node 里涉及 PEM / DERKeyObjectsign / verify。常见坑:

  • padding 模式(RSA-OAEP vs PKCS#1)与服务端不一致就验不过;
  • 把私钥当字符串到处传——权限与日志里都要收紧。

密码学安全随机crypto.randomBytes(或 randomInt 等),不要用 Math.random

用途:

  • session idCSRF tokennonce盐值
  • 只要「指纹」:哈希;要 防篡改且双方有共享密钥:HMAC;
  • 要藏内容且单方持有密钥:对称加密(注意 IV 与认证);
  • 要身份不可否认或公钥体系:非对称签名 / 验签;
  • 所有密钥与随机数crypto安全存储,不要自创「混淆算法」。

crypto 按上面几条分类,再去看 HTTPS(TLS 终止在哪)、JWT、对象存储预签名 URL,会知道各自落在哪一层。