Skip to content

NOTE

Bun implementa le funzioni `createHash` e `createHmac` da [`node:crypto`](https://nodejs.org/api/crypto.html) in aggiunta alle API native di Bun documentate di seguito.

Bun.password

Bun.password è una raccolta di funzioni utility per hash e verifica di password con vari algoritmi crittograficamente sicuri.

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

Il secondo argomento di Bun.password.hash accetta un oggetto params che ti permette di scegliere e configurare l'algoritmo di hashing.

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

// usa argon2 (default)
const argonHash = await Bun.password.hash(password, {
  algorithm: "argon2id", // "argon2id" | "argon2i" | "argon2d"
  memoryCost: 4, // uso di memoria in kibibyte
  timeCost: 3, // numero di iterazioni
});

// usa bcrypt
const bcryptHash = await Bun.password.hash(password, {
  algorithm: "bcrypt",
  cost: 4, // numero tra 4-31
});

L'algoritmo usato per creare l'hash è memorizzato nell'hash stesso. Quando si usa bcrypt, l'hash restituito è codificato in Modular Crypt Format per compatibilità con la maggior parte delle implementazioni bcrypt esistenti; con argon2 il risultato è codificato nel più recente formato PHC.

La funzione verify rileva automaticamente l'algoritmo in base all'hash di input e usa il metodo di verifica corretto. Può dedurre correttamente l'algoritmo da hash codificati sia in PHC che in 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

Sono disponibili anche versioni sincrone di tutte le funzioni. Tieni presente che queste funzioni sono computazionalmente costose, quindi usare un'API bloccante può degradare le prestazioni dell'applicazione.

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

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

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

Salt

Quando usi Bun.password.hash, un salt viene generato automaticamente e incluso nell'hash.

bcrypt - Modular Crypt Format

Nel seguente hash in Modular Crypt Format (usato da bcrypt):

Input:

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

Output:

sh
$2b$10$Lyj9kHYZtiyfxh2G60TEfeqs7xkkGiEFFDi3iJGc50ZG/XJ1sxIFi;

Il formato è composto da:

  • bcrypt: $2b
  • rounds: $10 - round (log10 del numero effettivo di round)
  • salt: $Lyj9kHYZtiyfxh2G60TEfeqs7xkkGiEFFDi3iJGc50ZG/XJ1sxIFi
  • hash: $GzJ8PuBi+K+BVojzPfS5mjnC8OpLGtv8KJqF99eP6a4

Per impostazione predefinita, la libreria bcrypt tronca le password più lunghe di 72 byte. In Bun, se passi a Bun.password.hash una password più lunga di 72 byte e usi l'algoritmo bcrypt, la password verrà hashata tramite SHA-512 prima di essere passata a bcrypt.

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

Quindi invece di inviare a bcrypt una password di 500 byte silenziosamente troncata a 72 byte, Bun hasherà la password usando SHA-512 e invierà la password hashata a bcrypt (solo se supera i 72 byte). Questo è un comportamento predefinito più sicuro.

argon2 - formato PHC

Nel seguente hash in formato PHC (usato da argon2):

Input:

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

Output:

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

Il formato è composto da:

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

Bun.hash

Bun.hash è una raccolta di utility per hashing non crittografico. Gli algoritmi di hashing non crittografico sono ottimizzati per la velocità di calcolo rispetto alla resistenza alle collisioni o alla sicurezza.

La funzione standard Bun.hash usa Wyhash per generare un hash a 64 bit da un input di dimensioni arbitrarie.

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

L'input può essere una stringa, 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));

Opzionalmente, un seed intero può essere specificato come secondo parametro. Per hash a 64 bit, i seed superiori a Number.MAX_SAFE_INTEGER dovrebbero essere dati come BigInt per evitare perdita di precisione.

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

Algoritmi di hashing aggiuntivi sono disponibili come proprietà su Bun.hash. L'API è la stessa per ciascuno, cambiando solo il tipo di restituzione da numero per hash a 32 bit a bigint per hash a 64 bit.

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 è una classe utility generica che ti permette di calcolare incrementalmente un hash di dati stringa o binari usando una gamma di algoritmi di hash crittografici. Sono supportati i seguenti algoritmi:

  • "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 volta inizializzato, i dati possono essere forniti incrementalmente all'hasher usando .update(). Questo metodo accetta string, TypedArray e ArrayBuffer.

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

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

Se viene passata una string, un secondo parametro opzionale può essere usato per specificare la codifica (default 'utf-8'). Sono supportate le seguenti codifiche:

CategoriaCodifiche
Codifiche binarie"base64" "base64url" "hex" "binary"
Codifiche di caratteri"utf8" "utf-8" "utf16le" "latin1"
Codifiche di caratteri legacy"ascii" "binary" "ucs2" "ucs-2"
ts
hasher.update("hello world"); // default a utf8
hasher.update("hello world", "hex");
hasher.update("hello world", "base64");
hasher.update("hello world", "latin1");

Dopo che i dati sono stati forniti all'hasher, un hash finale può essere calcolato usando .digest(). Per impostazione predefinita, questo metodo restituisce un Uint8Array contenente l'hash.

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

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

Il metodo .digest() può opzionalmente restituire l'hash come stringa. Per farlo, specifica una codifica:

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

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

In alternativa, il metodo può scrivere l'hash in un'istanza TypedArray preesistente. Questo può essere desiderabile in alcune applicazioni sensibili alle prestazioni.

ts
const arr = new Uint8Array(32);

hasher.digest(arr);

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

HMAC in Bun.CryptoHasher

Bun.CryptoHasher può essere usato per calcolare digest HMAC. Per farlo, passa la chiave al costruttore.

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

Quando si usa HMAC, è supportato un insieme più limitato di algoritmi:

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

A differenza del Bun.CryptoHasher non-HMAC, l'istanza Bun.CryptoHasher HMAC non viene resettata dopo che .digest() viene chiamato, e tentare di usare la stessa istanza di nuovo lancerà un errore.

Altri metodi come .copy() e .update() sono supportati (purché sia prima di .digest()), ma metodi come .digest() che finalizzano l'hasher non lo sono.

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 a cura di www.bunjs.com.cn