Skip to content

NOTE

Bun реализует функции `createHash` и `createHmac` из [`node:crypto`](https://nodejs.org/api/crypto.html) в дополнение к нативным API Bun, документированным ниже.

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, // использование памяти в кибибайтах
  timeCost: 3, // количество итераций
});

// использовать bcrypt
const bcryptHash = await Bun.password.hash(password, {
  algorithm: "bcrypt",
  cost: 4, // число от 4 до 31
});

Алгоритм, использованный для создания хеша, хранится в самом хеше. При использовании bcrypt возвращённый хеш кодируется в Modular Crypt Format для совместимости с большинством существующих реализаций bcrypt; с argon2 результат кодируется в более новом PHC формате.

Функция 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
  • раунды: $10 — раунды (log10 фактического количества раундов)
  • соль: $Lyj9kHYZtiyfxh2G60TEfeqs7xkkGiEFFDi3iJGc50ZG/XJ1sxIFi
  • хеш: $GzJ8PuBi+K+BVojzPfS5mjnC8OpLGtv8KJqF99eP6a4

По умолчанию библиотека bcrypt обрезает пароли длиннее 72 байт. В Bun, если вы передадите Bun.password.hash пароль длиннее 72 байт и используете алгоритм bcrypt, пароль будет хеширован через SHA-512 перед передачей в bcrypt.

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

Таким образом, вместо тихой передачи bcrypt пароля в 500 байт, обрезанного до 72 байт, Bun хеширует пароль с помощью SHA-512 и передаёт хешированный пароль в bcrypt (только если он превышает 72 байта). Это более безопасное поведение по умолчанию.

argon2 - PHC формат

В следующем хеше PHC формата (используется argon2):

Ввод:

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

Вывод:

sh
$argon2id$v=19$m=65536,t=2,p=1$xXnlSvPh4ym5KYmxKAuuHVlDvy2QGHBNuI6bJJrRDOs$2YY6M48XmHn+s5NoBaL+ficzXajq2Yj8wut3r0vnrwI

Формат состоит из:

  • алгоритм: $argon2id
  • версия: $v=19
  • стоимость памяти: 65536
  • итерации: t=2
  • параллелизм: p=1
  • соль: $xXnlSvPh4ym5KYmxKAuuHVlDvy2QGHBNuI6bJJrRDOs
  • хеш: $2YY6M48XmHn+s5NoBaL+ficzXajq2Yj8wut3r0vnrwI

Bun.hash

Bun.hash — это коллекция утилит для некриптографического хеширования. Некриптографические алгоритмы хеширования оптимизированы для скорости вычислений, а не для устойчивости к коллизиям или безопасности.

Стандартная функция Bun.hash использует Wyhash для генерации 64-битного хеша из входных данных произвольного размера.

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

Входные данные могут быть строкой, TypedArray, DataView, ArrayBuffer или SharedArrayBuffer.

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 одинаков для каждого, меняется только тип возвращаемого значения с number для 32-битных хешей на bigint для 64-битных хешей.

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(). Этот метод принимает string, TypedArray и ArrayBuffer.

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, ... ]

HMAC в Bun.CryptoHasher

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