Skip to content

NOTE

Bun 實現了 [`node:crypto`](https://nodejs.org/api/crypto.html) 中的 `createHash` 和 `createHmac` 函數, 此外還有下面記錄的 Bun 原生 API。

Bun.password

Bun.password 是一組用於使用各種加密安全算法進行哈希和密碼驗證的實用函數集合。

ts
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
const password = "super-secure-pa$$word";

// 使用 argon2(默認)
const argonHash = await Bun.password.hash(password, {
  algorithm: "argon2id", // "argon2id" | "argon2i" | "argon2d"
  memoryCost: 4, // 內存使用量(kibibytes)
  timeCost: 3, // 迭代次數
});

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

用於創建哈希的算法存儲在哈希本身中。使用 bcrypt 時,返回的哈希以 Modular Crypt Format 編碼,以與大多數現有 bcrypt 實現兼容;使用 argon2 時,結果以較新的 PHC format 編碼。

verify 函數根據輸入哈希自動檢測算法並使用正確的驗證方法。它可以正確地從 PHC 或 MCF 編碼的哈希中推斷算法。

ts
const password = "super-secure-pa$$word";

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

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

所有函數的同步版本也可用。請記住,這些函數計算成本很高,因此使用阻塞 API 可能會降低應用程序性能。

ts
const password = "super-secure-pa$$word";

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

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

當你使用 Bun.password.hash 時,會自動生成一個鹽並包含在哈希中。

bcrypt - Modular Crypt Format

在以下 Modular Crypt Format 哈希(bcrypt 使用)中:

輸入:

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

輸出:

sh
$2b$10$Lyj9kHYZtiyfxh2G60TEfeqs7xkkGiEFFDi3iJGc50ZG/XJ1sxIFi;

格式由以下部分組成:

  • bcrypt: $2b
  • rounds: $10 - 輪數(實際輪數的 log10)
  • salt: $Lyj9kHYZtiyfxh2G60TEfeqs7xkkGiEFFDi3iJGc50ZG/XJ1sxIFi
  • hash: $GzJ8PuBi+K+BVojzPfS5mjnC8OpLGtv8KJqF99eP6a4

默認情況下,bcrypt 庫會截斷超過 72 字節的密碼。在 Bun 中,如果你傳遞給 Bun.password.hash 的密碼超過 72 字節並使用 bcrypt 算法,密碼將在傳遞給 bcrypt 之前通過 SHA-512 進行哈希。

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

因此,Bun 不會靜默地將 500 字節的密碼截斷為 72 字節傳遞給 bcrypt,而是使用 SHA-512 對密碼進行哈希並將哈希後的密碼發送給 bcrypt(僅當超過 72 字節時)。這是更安全的默認行為。

argon2 - PHC 格式

在以下 PHC format 哈希(argon2 使用)中:

輸入:

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

輸出:

sh
$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 從任意大小的輸入生成 64 位哈希。

ts
Bun.hash("some data here");
// 11562320457524636935n

輸入可以是字符串、TypedArrayDataViewArrayBufferSharedArrayBuffer

ts
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
Bun.hash("some data here", 1234);
// 15724820720172937558n

Bun.hash 的屬性上提供了其他哈希算法。每個 API 都相同,只是將 32 位哈希的返回類型從 number 更改為 64 位哈希的 bigint。

ts
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"
  • "md4"
  • "md5"
  • "ripemd160"
  • "sha1"
  • "sha224"
  • "sha256"
  • "sha384"
  • "sha512"
  • "sha512-224"
  • "sha512-256"
  • "sha3-224"
  • "sha3-256"
  • "sha3-384"
  • "sha3-512"
  • "shake128"
  • "shake256"
ts
const hasher = new Bun.CryptoHasher("sha256");
hasher.update("hello world");
hasher.digest();
// Uint8Array(32) [ <byte>, <byte>, ... ]

初始化後,可以使用 .update() 增量將數據饋送到哈希器。此方法接受 stringTypedArrayArrayBuffer

ts
const hasher = new Bun.CryptoHasher("sha256");

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

如果傳遞 string,可以使用可選的第二個參數指定編碼(默認 'utf-8')。支持以下編碼:

類別編碼
二進制編碼"base64" "base64url" "hex" "binary"
字符編碼"utf8" "utf-8" "utf16le" "latin1"
傳統字符編碼"ascii" "binary" "ucs2" "ucs-2"
ts
hasher.update("hello world"); // 默認為 utf8
hasher.update("hello world", "hex");
hasher.update("hello world", "base64");
hasher.update("hello world", "latin1");

數據饋送到哈希器後,可以使用 .digest() 計算最終哈希。默認情況下,此方法返回包含哈希的 Uint8Array

ts
const hasher = new Bun.CryptoHasher("sha256");
hasher.update("hello world");

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

.digest() 方法可選地將哈希作為字符串返回。為此,請指定編碼:

ts
hasher.digest("base64");
// => "uU0nuZNNPgilLlLX2n2r+sSE7+N6U4DukIj3rOLvzek="

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

或者,該方法可以將哈希寫入預先存在的 TypedArray 實例。這可能在某些性能敏感應用中需要。

ts
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
const hasher = new Bun.CryptoHasher("sha256", "secret-key");
hasher.update("hello world");
console.log(hasher.digest("hex"));
// => "095d5a21fe6d0646db223fdf3de6436bb8dfb2fab0b51677ecf6441fcf5f2a67"

使用 HMAC 時,支持的算法集更有限:

  • "blake2b512"
  • "md5"
  • "sha1"
  • "sha224"
  • "sha256"
  • "sha384"
  • "sha512-224"
  • "sha512-256"
  • "sha512"

與非 HMAC Bun.CryptoHasher 不同,HMAC Bun.CryptoHasher 實例在調用 .digest() 後不會重置,嘗試再次使用同一實例將拋出錯誤。

支持其他方法如 .copy().update()(只要在 .digest() 之前),但不支持像 .digest() 這樣最終確定哈希器的方法。

ts
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"

Bun學習網由www.bunjs.com.cn整理維護