返回文章列表 →

Note

crypto

Node.js 内置的密码学模块,提供安全随机数、哈希、HMAC、加密解密、数字签名、密钥生成等能力

发布于 更新于

crypto

是 Node.js 内置的密码学模块,不是第三方库,它提供安全随机数、哈希、HMAC、加密解密、数字签名、密钥生成等能力。

引入

// node: 前缀表示这是 Node.js 核心模块,可以避免与 npm 中同名包混淆
import { createHmac, randomInt, timingSafeEqual } from "node:crypto";

// 也可以不使用node前缀。但是建议写前缀,因为可以一眼看出它不是第三方依赖,代码语义更加清晰
import * as crypto from "crypto";

randomInt()

生成指定范围内的密码学安全随机整数

参数与返回值

// 同步
randomInt(
  min: number,
  max: number,
): number;

// 省略min
randomInt(
  max: number,
): number;

// 异步
randomInt(
  min: number,
  max: number,
  callback: (error: Error | null, value: number) => void,
): void;
参数 含义
min 随机数最小值,包含该值;省略时默认为 0
max 随机数最大边界,不包含该值
callback 可选回调函数;提供后使用异步方式生成
返回值 不传回调时返回随机整数 number

示例

const value = randomInt(0, 10); // 可能得到0、1、2、3、4、5、6、7、8、9

// 生成随机6位数字。其中 1_000_000 与 1000000 完全相同,下划线只是方便阅读
const code = randomInt(0, 1_000_000).toString().padStart(6, "0");

createHmac()

使用“哈希算法 + 服务端密钥”创建一个 HMAC 计算对象。HMAC 可以简单理解为:

HMAC结果 = 密钥 + 原始数据 + 哈希算法共同计算出的摘要

例如
算法:SHA-256
密钥:my-secret
数据:test@example.com:REGISTER:123456

只要密钥或数据有任何变化,计算结果就会变化

HMAC 不是加密。不能从 HMAC 结果还原验证码,相同密钥和相同数据,会产生相同结果,没有服务端密钥,就无法正常计算对应结果

参数与返回值

createHmac(
  algorithm: string,
  key:
    | string
    | Buffer
    | ArrayBuffer
    | TypedArray
    | DataView
    | KeyObject,
  options?: object,
): Hmac;
参数 含义
algorithm 使用的哈希算法,例如 'sha256'、'sha512'
key HMAC 密钥,也就是你代码中的 pepper
options 可选的流配置;普通验证码场景通常不需要
返回值 返回一个 Hmac 对象,还不是最终字符串

示例

// 1.创建计算器。此时只是创建了计算器,还没有告诉它要处理哪些数据
const hmac = createHmac("sha256", "my-secret");

hmac.update()

向 HMAC 对象中加入需要计算的数据

参数与返回值
hmac.update(
  data: string | Buffer | TypedArray | DataView,
  inputEncoding?: string,
): Hmac;
参数 含义
data 要参与 HMAC 计算的数据
inputEncoding 数据是字符串时所用的编码,默认是 'utf8'
返回值 返回当前 Hmac 对象,所以可以继续链式调用
示例
// 2.向 HMAC 对象中加入需要计算的数据
hmac.update(data);

hmac.digest()

完成 HMAC 计算并取得最终结果

参数与返回值
hmac.digest(): Buffer;

hmac.digest(
  encoding: string,
): string;
参数 含义
encoding 可选输出编码,例如 'hex'、'base64'
不传编码 返回二进制 Buffer
传入 'hex' 返回十六进制字符串
传入 'base64' 返回 Base64 字符串
示例
// 3.完成 HMAC 计算并取得最终结果
hmac.digest("hex");

完整示例

完整使用“哈希算法 + 服务端密钥”创建一个 HMAC 计算对象

const result = createHmac("sha256", "my-secret")
  .update("需要处理的数据")
  .digest("hex");

timingSafeEqual()

安全地比较两段二进制数据是否完全相同。

参数与返回值

// a 和 b 的字节长度必须一致,否则会抛出异常
timingSafeEqual(
  a: Buffer | ArrayBuffer | TypedArray | DataView,
  b: Buffer | ArrayBuffer | TypedArray | DataView,
): boolean;
参数 含义
a 第一段二进制数据
b 第二段二进制数据
返回值 相同返回 true,不同返回 false

示例

expected.length === actual.length && timingSafeEqual(expected, actual);