> ## Documentation Index
> Fetch the complete documentation index at: https://bun.ll1025.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 哈希

> 使用各种加密安全算法进行哈希和密码验证的实用函数

<Note>
  除了下面记录的 Bun 原生 API 外，Bun 还实现了 [`node:crypto`](https://nodejs.org/api/crypto.html) 中的 `createHash` 和 `createHmac` 函数。
</Note>

***

## `Bun.password`

`Bun.password` 是一组实用函数，用于使用各种加密安全算法进行密码哈希和验证。

```ts theme={null}
const password = "super-secure-pa$$word";

const hash = await Bun.password.hash(password);
// => $argon2id$v=19$m=65536,t=2,p=1$tFq+9AVr1bfPxQdh6E8DQRhEXg/M/SqYCNu6gVdRRNs$GzJ8PuBi+K+BVojzPfS5mjnC8OpLGtv8KJqF99eP6a4

const isMatch = await Bun.password.verify(password, hash);
// => true
```

`Bun.password.hash` 的第二个参数是一个参数对象，用于选择并配置哈希算法。

```ts theme={null}
const password = "super-secure-pa$$word";

// 使用 argon2（默认）
const argonHash = await Bun.password.hash(password, {
  algorithm: "argon2id", // "argon2id" | "argon2i" | "argon2d"
  memoryCost: 8, // 内存使用量（KiB，最小 8）
  timeCost: 3, // 迭代次数
});

// 使用 bcrypt
const bcryptHash = await Bun.password.hash(password, {
  algorithm: "bcrypt",
  cost: 4, // 4-31 之间的数字
});
```

用于创建哈希的算法存储在哈希本身中。使用 `bcrypt` 时，返回的哈希以[模块化加密格式](https://passlib.readthedocs.io/en/stable/modular_crypt_format.html)编码，以便与大多数现有 `bcrypt` 实现兼容；使用 `argon2` 时，结果以更新的 [PHC 格式](https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md)编码。

`verify` 函数会自动检测输入哈希中的算法，无论是 PHC 编码还是 MCF 编码，并使用匹配的验证方法。

```ts theme={null}
const password = "super-secure-pa$$word";

const hash = await Bun.password.hash(password, {
  /* 配置 */
});

const isMatch = await Bun.password.verify(password, hash);
// => true
```

所有函数的同步版本也可用。这些函数计算量大，因此阻塞 API 可能会降低应用程序性能。

```ts theme={null}
const password = "super-secure-pa$$word";

const hash = Bun.password.hashSync(password, {
  /* 配置 */
});

const isMatch = Bun.password.verifySync(password, hash);
// => true
```

### 盐值

`Bun.password.hash` 自动生成盐值并将其包含在哈希中。

### bcrypt - 模块化加密格式

以下[模块化加密格式](https://passlib.readthedocs.io/en/stable/modular_crypt_format.html)哈希（由 `bcrypt` 使用）：

输入：

```ts theme={null}
await Bun.password.hash("hello", {
  algorithm: "bcrypt",
});
```

输出：

```sh theme={null}
$2b$10$Lyj9kHYZtiyfxh2G60TEfeqs7xkkGiEFFDi3iJGc50ZG/XJ1sxIFi;
```

格式由以下部分组成：

* `bcrypt`：`$2b`
* `rounds`：`$10` - 轮次（实际轮数的 log2）
* `salt`：`Lyj9kHYZtiyfxh2G60TEfe`
* `hash`：`qs7xkkGiEFFDi3iJGc50ZG/XJ1sxIFi`

默认情况下，bcrypt 库会截断超过 72 字节的密码。为了避免静默截断，对 `bcrypt` 算法的 `Bun.password.hash` 会在将密码传递给 bcrypt 之前，对超过 72 字节的密码使用 SHA-512 进行哈希。

```ts theme={null}
await Bun.password.hash("hello".repeat(100), {
  algorithm: "bcrypt",
});
```

### argon2 - PHC 格式

以下 [PHC 格式](https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md)哈希（由 `argon2` 使用）：

输入：

```ts theme={null}
await Bun.password.hash("hello", {
  algorithm: "argon2id",
});
```

输出：

```sh theme={null}
$argon2id$v=19$m=65536,t=2,p=1$xXnlSvPh4ym5KYmxKAuuHVlDvy2QGHBNuI6bJJrRDOs$2YY6M48XmHn+s5NoBaL+ficzXajq2Yj8wut3r0vnrwI
```

格式由以下部分组成：

* `algorithm`：`$argon2id`
* `version`：`$v=19`
* `memory cost`：`65536`
* `iterations`：`t=2`
* `parallelism`：`p=1`
* `salt`：`$xXnlSvPh4ym5KYmxKAuuHVlDvy2QGHBNuI6bJJrRDOs`
* `hash`：`$2YY6M48XmHn+s5NoBaL+ficzXajq2Yj8wut3r0vnrwI`

***

## `Bun.hash`

`Bun.hash` 是一组用于**非加密**哈希的实用工具。非加密哈希算法针对计算速度进行了优化，而非抗碰撞性或安全性。

标准的 `Bun.hash` 函数使用 [Wyhash](https://github.com/wangyi-fudan/wyhash) 从任意大小的输入生成 64 位哈希。

```ts theme={null}
Bun.hash("some data here");
// 11562320457524636935n
```

输入可以是字符串、`TypedArray`、`DataView`、`ArrayBuffer` 或 `SharedArrayBuffer`。

```ts theme={null}
const arr = new Uint8Array([1, 2, 3, 4]);

Bun.hash("some data here");
Bun.hash(arr);
Bun.hash(arr.buffer);
Bun.hash(new DataView(arr.buffer));
```

第二个参数是一个可选整数种子。对于 64 位哈希，将超过 `Number.MAX_SAFE_INTEGER` 的种子作为 BigInt 传递，以避免精度损失。

```ts theme={null}
Bun.hash("some data here", 1234);
// 15724820720172937558n
```

其他哈希算法作为 `Bun.hash` 的属性可用。每个算法的 API 相同；32 位哈希返回数字，64 位哈希返回 bigint。

```ts theme={null}
Bun.hash.wyhash("data", 1234); // 等同于 Bun.hash()
Bun.hash.crc32("data", 1234);
Bun.hash.adler32("data", 1234);
Bun.hash.cityHash32("data", 1234);
Bun.hash.cityHash64("data", 1234);
Bun.hash.xxHash32("data", 1234);
Bun.hash.xxHash64("data", 1234);
Bun.hash.xxHash3("data", 1234);
Bun.hash.murmur32v3("data", 1234);
Bun.hash.murmur32v2("data", 1234);
Bun.hash.murmur64v2("data", 1234);
Bun.hash.rapidhash("data", 1234);
```

***

## `Bun.CryptoHasher`

`Bun.CryptoHasher` 使用加密哈希算法增量计算字符串或二进制数据的哈希值。支持以下算法：

* `"blake2b256"`
* `"blake2b512"`
* `"blake2s256"`
* `"md4"`
* `"md5"`
* `"ripemd160"`
* `"sha1"`
* `"sha224"`
* `"sha256"`
* `"sha384"`
* `"sha512"`
* `"sha512-224"`
* `"sha512-256"`
* `"sha3-224"`
* `"sha3-256"`
* `"sha3-384"`
* `"sha3-512"`
* `"shake128"`
* `"shake256"`

```ts theme={null}
const hasher = new Bun.CryptoHasher("sha256");
hasher.update("hello world");
hasher.digest();
// Uint8Array(32) [ <byte>, <byte>, ... ]
```

使用 `.update()` 增量地向 hasher 提供数据，该方法接受 `string`、`TypedArray` 和 `ArrayBuffer`。

```ts theme={null}
const hasher = new Bun.CryptoHasher("sha256");

hasher.update("hello world");
hasher.update(new Uint8Array([1, 2, 3]));
hasher.update(new ArrayBuffer(10));
```

对于字符串，可选的第二个参数指定编码（默认 `'utf-8'`）。支持以下编码：

| 类别     | 编码                                          |
| ------ | ------------------------------------------- |
| 二进制编码  | `"base64"` `"base64url"` `"hex"` `"binary"` |
| 字符编码   | `"utf8"` `"utf-8"` `"utf16le"` `"latin1"`   |
| 旧版字符编码 | `"ascii"` `"binary"` `"ucs2"` `"ucs-2"`     |

```ts theme={null}
hasher.update("hello world"); // 默认为 utf8
hasher.update("hello world", "hex");
hasher.update("hello world", "base64");
hasher.update("hello world", "latin1");
```

所有数据输入完成后，使用 `.digest()` 计算最终哈希值。默认情况下，此方法返回包含哈希值的 `Uint8Array`。

```ts theme={null}
const hasher = new Bun.CryptoHasher("sha256");
hasher.update("hello world");

hasher.digest();
// => Uint8Array(32) [ 185, 77, 39, 185, 147, ... ]
```

要获取哈希字符串，向 `.digest()` 传递编码参数：

```ts theme={null}
hasher.digest("base64");
// => "uU0nuZNNPgilLlLX2n2r+sSE7+N6U4DukIj3rOLvzek="

hasher.digest("hex");
// => "b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9"
```

或者，`.digest()` 可以将哈希值写入现有的 `TypedArray` 中，而不是分配新的。

```ts theme={null}
const arr = new Uint8Array(32);

hasher.digest(arr);

console.log(arr);
// => Uint8Array(32) [ 185, 77, 39, 185, 147, ... ]
```

### `Bun.CryptoHasher` 中的 HMAC

`Bun.CryptoHasher` 可以计算 HMAC 摘要。将密钥传递给构造函数。

```ts theme={null}
const hasher = new Bun.CryptoHasher("sha256", "secret-key");
hasher.update("hello world");
console.log(hasher.digest("hex"));
// => "095d5a21fe6d0646db223fdf3de6436bb8dfb2fab0b51677ecf6441fcf5f2a67"
```

HMAC 支持的算法范围更有限：

* `"blake2b256"`
* `"blake2b512"`
* `"md4"`
* `"md5"`
* `"ripemd160"`
* `"sha1"`
* `"sha224"`
* `"sha256"`
* `"sha384"`
* `"sha512"`
* `"sha512-224"`
* `"sha512-256"`
* `"sha3-224"`
* `"sha3-256"`
* `"sha3-384"`
* `"sha3-512"`

与非 HMAC 的 `Bun.CryptoHasher` 不同，HMAC 的 `Bun.CryptoHasher` 实例在调用 `.digest()` 后不会重置，再次使用同一个实例会抛出错误。

其他方法如 `.copy()` 和 `.update()` 受支持（只要在 `.digest()` 之前调用），但像 `.digest()` 这样结束 hasher 的方法不支持。

```ts theme={null}
const hasher = new Bun.CryptoHasher("sha256", "secret-key");
hasher.update("hello world");

const copy = hasher.copy();
copy.update("!");
console.log(copy.digest("hex"));
// => "3840176c3d8923f59ac402b7550404b28ab11cb0ef1fa199130a5c37864b5497"

console.log(hasher.digest("hex"));
// => "095d5a21fe6d0646db223fdf3de6436bb8dfb2fab0b51677ecf6441fcf5f2a67"
```
