Skip to content

NOTE

Bun implementa las funciones `createHash` y `createHmac` de [`node:crypto`](https://nodejs.org/api/crypto.html) además de las APIs nativas de Bun documentadas a continuación.

Bun.password

Bun.password es una colección de funciones utilitarias para hashear y verificar contraseñas con varios algoritmos criptográficamente seguros.

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

El segundo argumento de Bun.password.hash acepta un objeto de parámetros que te permite elegir y configurar el algoritmo de hashing.

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

// usar argon2 (predeterminado)
const argonHash = await Bun.password.hash(password, {
  algorithm: "argon2id", // "argon2id" | "argon2i" | "argon2d"
  memoryCost: 4, // uso de memoria en kibibytes
  timeCost: 3, // el número de iteraciones
});

// usar bcrypt
const bcryptHash = await Bun.password.hash(password, {
  algorithm: "bcrypt",
  cost: 4, // número entre 4-31
});

El algoritmo usado para crear el hash se almacena en el propio hash. Al usar bcrypt, el hash devuelto se codifica en Modular Crypt Format para compatibilidad con la mayoría de implementaciones existentes de bcrypt; con argon2 el resultado se codifica en el nuevo formato PHC.

La función verify detecta automáticamente el algoritmo basado en el hash de entrada y usa el método de verificación correcto. Puede inferir correctamente el algoritmo tanto de hashes codificados en PHC como en MCF.

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

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

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

También están disponibles versiones síncronas de todas las funciones. Ten en cuenta que estas funciones son computacionalmente costosas, por lo que usar una API de bloqueo puede degradar el rendimiento de la aplicación.

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

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

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

Sal

Cuando usas Bun.password.hash, se genera automáticamente una sal y se incluye en el hash.

bcrypt - Formato Modular Crypt

En el siguiente hash de Modular Crypt Format (usado por bcrypt):

Entrada:

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

Salida:

sh
$2b$10$Lyj9kHYZtiyfxh2G60TEfeqs7xkkGiEFFDi3iJGc50ZG/XJ1sxIFi;

El formato está compuesto por:

  • bcrypt: $2b
  • rounds: $10 - rondas (log10 del número real de rondas)
  • salt: $Lyj9kHYZtiyfxh2G60TEfeqs7xkkGiEFFDi3iJGc50ZG/XJ1sxIFi
  • hash: $GzJ8PuBi+K+BVojzPfS5mjnC8OpLGtv8KJqF99eP6a4

Por defecto, la biblioteca bcrypt trunca contraseñas más largas de 72 bytes. En Bun, si pasas a Bun.password.hash una contraseña más larga de 72 bytes y usas el algoritmo bcrypt, la contraseña se hasheará vía SHA-512 antes de pasarse a bcrypt.

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

Así que en lugar de enviar a bcrypt una contraseña de 500 bytes truncada silenciosamente a 72 bytes, Bun hasheará la contraseña usando SHA-512 y enviará la contraseña hasheada a bcrypt (solo si excede 72 bytes). Este es un comportamiento predeterminado más seguro.

argon2 - Formato PHC

En el siguiente hash de formato PHC (usado por argon2):

Entrada:

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

Salida:

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

El formato está compuesto por:

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

Bun.hash

Bun.hash es una colección de utilidades para hashing no criptográfico. Los algoritmos de hashing no criptográficos están optimizados para velocidad de cómputo sobre resistencia a colisiones o seguridad.

La función estándar Bun.hash usa Wyhash para generar un hash de 64 bits desde una entrada de tamaño arbitrario.

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

La entrada puede ser una cadena, TypedArray, DataView, ArrayBuffer, o 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));

Opcionalmente, se puede especificar una semilla entera como segundo parámetro. Para hashes de 64 bits, las semillas por encima de Number.MAX_SAFE_INTEGER deben darse como BigInt para evitar pérdida de precisión.

ts
Bun.hash("some data here", 1234);
// 15724820720172937558n

Hay algoritmos de hashing adicionales disponibles como propiedades en Bun.hash. La API es la misma para cada uno, solo cambiando el tipo de retorno de number para hashes de 32 bits a bigint para hashes de 64 bits.

ts
Bun.hash.wyhash("data", 1234); // equivalente a 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 es una clase utilitaria de propósito general que te permite calcular incrementalmente un hash de cadena o datos binarios usando un rango de algoritmos de hash criptográficos. Se soportan los siguientes algoritmos:

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

Una vez inicializado, se pueden alimentar datos incrementalmente al hasher usando .update(). Este método acepta string, TypedArray, y ArrayBuffer.

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

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

Si se pasa una string, se puede usar un segundo parámetro opcional para especificar la codificación (predeterminado 'utf-8'). Se soportan las siguientes codificaciones:

CategoríaCodificaciones
Codificaciones binarias"base64" "base64url" "hex" "binary"
Codificaciones de caracteres"utf8" "utf-8" "utf16le" "latin1"
Codificaciones de caracteres heredadas"ascii" "binary" "ucs2" "ucs-2"
ts
hasher.update("hello world"); // predeterminado utf8
hasher.update("hello world", "hex");
hasher.update("hello world", "base64");
hasher.update("hello world", "latin1");

Después de que los datos se han alimentado al hasher, se puede calcular un hash final usando .digest(). Por defecto, este método devuelve un Uint8Array conteniendo el hash.

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

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

El método .digest() puede opcionalmente devolver el hash como una cadena. Para hacerlo, especifica una codificación:

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

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

Alternativamente, el método puede escribir el hash en una instancia TypedArray preexistente. Esto puede ser deseable en algunas aplicaciones sensibles al rendimiento.

ts
const arr = new Uint8Array(32);

hasher.digest(arr);

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

HMAC en Bun.CryptoHasher

Bun.CryptoHasher se puede usar para calcular dígestos HMAC. Para hacerlo, pasa la clave al constructor.

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

Al usar HMAC, se soporta un conjunto más limitado de algoritmos:

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

A diferencia del Bun.CryptoHasher no HMAC, la instancia de Bun.CryptoHasher HMAC no se reinicia después de llamar a .digest(), y intentar usar la misma instancia nuevamente lanzará un error.

Otros métodos como .copy() y .update() se soportan (siempre que sea antes de .digest()), pero métodos como .digest() que finalizan el hasher no se soportan.

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 por www.bunjs.com.cn editar