CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-noble--hashes

Audited & minimal 0-dependency JS implementation of SHA, RIPEMD, BLAKE, HMAC, HKDF, PBKDF & Scrypt

Overview
Eval results
Files

blake.mddocs/

BLAKE Hashing: BLAKE1, BLAKE2, and BLAKE3

The BLAKE family includes three generations of high-performance cryptographic hash functions. BLAKE2 is faster than MD5, SHA-1, and SHA-2 while being as secure as SHA-3. BLAKE3 is even faster with additional features like tree hashing, keyed hashing, and extendable output.

Imports

// BLAKE1 (legacy)
import { blake224, blake256, blake384, blake512 } from '@noble/hashes/blake1.js';

// BLAKE2
import { blake2b, blake2s } from '@noble/hashes/blake2.js';

// BLAKE3
import { blake3 } from '@noble/hashes/blake3.js';

Capabilities

BLAKE1 Hash Functions

BLAKE1 was one of the SHA-3 competition finalists. It is rarely used today and considered legacy. Included for compatibility with older systems.

/**
 * Options for BLAKE1 functions
 */
interface BlakeOpts {
  /** Salt value for domain separation (MUST be Uint8Array of exactly 16 bytes for all BLAKE1 variants) */
  salt?: Uint8Array;
}

/**
 * Computes BLAKE1-224 hash of input data
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.salt - Optional salt value (MUST be Uint8Array of exactly 16 bytes)
 * @returns 28-byte hash digest
 */
function blake224(msg: Uint8Array, opts?: BlakeOpts): Uint8Array;

// Properties
blake224.outputLen: 28; // Output length in bytes
blake224.blockLen: 64;  // Block length in bytes

// Create incremental hasher
function create(opts?: BlakeOpts): _BLAKE224;

/**
 * Computes BLAKE1-256 hash of input data
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.salt - Optional salt value (MUST be Uint8Array of exactly 16 bytes)
 * @returns 32-byte hash digest
 */
function blake256(msg: Uint8Array, opts?: BlakeOpts): Uint8Array;

// Properties
blake256.outputLen: 32; // Output length in bytes
blake256.blockLen: 64;  // Block length in bytes

// Create incremental hasher
function create(opts?: BlakeOpts): _BLAKE256;

/**
 * Computes BLAKE1-384 hash of input data
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.salt - Optional salt value (MUST be Uint8Array of exactly 16 bytes)
 * @returns 48-byte hash digest
 */
function blake384(msg: Uint8Array, opts?: BlakeOpts): Uint8Array;

// Properties
blake384.outputLen: 48;  // Output length in bytes
blake384.blockLen: 128;  // Block length in bytes

// Create incremental hasher
function create(opts?: BlakeOpts): _BLAKE384;

/**
 * Computes BLAKE1-512 hash of input data
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.salt - Optional salt value (MUST be Uint8Array of exactly 16 bytes)
 * @returns 64-byte hash digest
 */
function blake512(msg: Uint8Array, opts?: BlakeOpts): Uint8Array;

// Properties
blake512.outputLen: 64;  // Output length in bytes
blake512.blockLen: 128;  // Block length in bytes

// Create incremental hasher
function create(opts?: BlakeOpts): _BLAKE512;

Usage:

import { blake256 } from '@noble/hashes/blake1.js';

// Simple hash
const hash = blake256(data);

// With salt (must be exactly 16 bytes for all BLAKE1 variants)
const saltedHash = blake256(data, {
  salt: new Uint8Array(16).fill(0x42)
});

BLAKE2 Hash Functions

BLAKE2 is a fast, secure hash function suitable for general-purpose hashing, keyed hashing, and MAC. BLAKE2b targets 64-bit platforms while BLAKE2s targets 8-32 bit platforms.

/**
 * Options for BLAKE2 functions
 */
interface Blake2Opts {
  /** Desired output length in bytes (1-64 for blake2b, 1-32 for blake2s) */
  dkLen?: number;
  /** Key for keyed hashing/MAC (0-64 bytes for blake2b, 0-32 bytes for blake2s) */
  key?: Uint8Array;
  /** Salt for domain separation (MUST be Uint8Array of exactly 16 bytes for blake2b, 8 bytes for blake2s) */
  salt?: Uint8Array;
  /** Personalization string (MUST be Uint8Array of exactly 16 bytes for blake2b, 8 bytes for blake2s) */
  personalization?: Uint8Array;
}

/**
 * Computes BLAKE2b hash of input data (optimized for 64-bit platforms)
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.dkLen - Desired output length in bytes (1-64, default: 64)
 * @param opts.key - Optional key for keyed hashing (0-64 bytes)
 * @param opts.salt - Optional salt value (MUST be Uint8Array of exactly 16 bytes)
 * @param opts.personalization - Optional personalization string (MUST be Uint8Array of exactly 16 bytes)
 * @returns Hash digest of specified length
 */
function blake2b(msg: Uint8Array, opts?: Blake2Opts): Uint8Array;

// Properties
blake2b.outputLen: 64;  // Default output length in bytes
blake2b.blockLen: 128;  // Block length in bytes

// Create incremental hasher
function create(opts?: Blake2Opts): _BLAKE2b;

/**
 * Computes BLAKE2s hash of input data (optimized for 8-32 bit platforms)
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.dkLen - Desired output length in bytes (1-32, default: 32)
 * @param opts.key - Optional key for keyed hashing (0-32 bytes)
 * @param opts.salt - Optional salt value (MUST be Uint8Array of exactly 8 bytes)
 * @param opts.personalization - Optional personalization string (MUST be Uint8Array of exactly 8 bytes)
 * @returns Hash digest of specified length
 */
function blake2s(msg: Uint8Array, opts?: Blake2Opts): Uint8Array;

// Properties
blake2s.outputLen: 32; // Default output length in bytes
blake2s.blockLen: 64;  // Block length in bytes

// Create incremental hasher
function create(opts?: Blake2Opts): _BLAKE2s;

Usage:

import { blake2b, blake2s } from '@noble/hashes/blake2.js';
import { utf8ToBytes } from '@noble/hashes/utils.js';

// Simple hashing
const hash = blake2b(data);

// Custom output length
const hash256 = blake2b(data, { dkLen: 32 });

// Keyed hashing (MAC)
const key = new Uint8Array(32).fill(0x42);
const mac = blake2b(message, { key });

// With personalization (MUST be Uint8Array, exactly 16 bytes for blake2b)
// Use utf8ToBytes() to convert strings
const personalizationBytes = new Uint8Array(16);
personalizationBytes.set(utf8ToBytes('my-app-v1'));
const appHash = blake2b(data, {
  personalization: personalizationBytes,
  dkLen: 32
});

// With salt (MUST be Uint8Array, exactly 16 bytes for blake2b)
const saltBytes = new Uint8Array(16).fill(0x42);
const saltedHash = blake2b(data, {
  salt: saltBytes
});

// BLAKE2s for 32-bit platforms (salt and personalization are 8 bytes for blake2s)
const hash32 = blake2s(data);
const mac32 = blake2s(message, {
  key: new Uint8Array(32).fill(0x42)
});

// Incremental hashing
const hasher = blake2b.create({ dkLen: 32 });
hasher.update(chunk1);
hasher.update(chunk2);
const result = hasher.digest();

BLAKE3 Hash Function

BLAKE3 is the latest generation, offering even better performance with additional features like tree hashing, keyed mode, and key derivation context mode. Supports extendable output (XOF).

/**
 * Options for BLAKE3
 */
interface Blake3Opts {
  /** Desired output length in bytes (default: 32, unlimited for XOF) */
  dkLen?: number;
  /** 32-byte key for keyed mode (MAC) - mutually exclusive with context */
  key?: Uint8Array;
  /** Context for key derivation mode (MUST be Uint8Array, not string) - mutually exclusive with key */
  context?: Uint8Array;
}

/**
 * Computes BLAKE3 hash of input data
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.dkLen - Desired output length in bytes (default: 32)
 * @param opts.key - Optional 32-byte key for keyed mode (MAC)
 * @param opts.context - Optional context string for key derivation mode (MUST be Uint8Array, not string)
 * @returns Hash digest of specified length
 */
function blake3(msg: Uint8Array, opts?: Blake3Opts): Uint8Array;

// Properties
blake3.outputLen: 32;  // Default output length in bytes
blake3.blockLen: 64;   // Block length in bytes

// Create incremental hasher
function create(opts?: Blake3Opts): _BLAKE3;

BLAKE3 XOF Methods:

class _BLAKE3 {
  blockLen: number;
  outputLen: number;

  /**
   * Updates hash with new data
   * @param buf - Data to hash
   * @returns this for chaining
   */
  update(buf: Uint8Array): this;

  /**
   * Finalizes hash and returns digest
   * @returns Hash digest as Uint8Array
   */
  digest(): Uint8Array;

  /**
   * Finalizes hash and writes digest to provided buffer
   * @param out - Output buffer (must be >= outputLen)
   */
  digestInto(out: Uint8Array): void;

  /**
   * Reads bytes from XOF stream
   * @param bytes - Number of bytes to read
   * @returns Bytes from XOF stream
   */
  xof(bytes: number): Uint8Array;

  /**
   * Reads bytes from XOF into provided buffer
   * @param out - Output buffer
   * @returns The output buffer
   */
  xofInto(out: Uint8Array): Uint8Array;

  /**
   * Destroys internal state (zeros memory)
   */
  destroy(): void;

  /**
   * Creates independent copy of current hash state
   * @returns Cloned hash instance
   */
  clone(): _BLAKE3;
}

Usage:

import { blake3 } from '@noble/hashes/blake3.js';
import { utf8ToBytes } from '@noble/hashes/utils.js';

// Simple hashing
const hash = blake3(data);

// Custom output length
const hash512 = blake3(data, { dkLen: 64 });

// Keyed mode (MAC)
const key = new Uint8Array(32).fill(0x42);
const mac = blake3(message, { key });

// Key derivation context mode (MUST be Uint8Array, not string)
// Use utf8ToBytes() to convert strings
const derivedKey = blake3(inputMaterial, {
  context: utf8ToBytes('application-v1-encryption-key')
});

// XOF mode - read as much output as needed
const hasher = blake3.create();
hasher.update(data);

// Read multiple outputs from same hash state
const out1 = hasher.xof(32);
const out2 = hasher.xof(32);
const out3 = hasher.xof(64);

// Or use digest with custom length
const out = blake3(data, { dkLen: 256 }); // 256 bytes

BLAKE2 and BLAKE3 Class Interface

Both BLAKE2 and BLAKE3 instances implement a common interface:

interface Hash<T> {
  blockLen: number;
  outputLen: number;

  /**
   * Updates hash with new data
   * @param buf - Data to hash
   * @returns this for chaining
   */
  update(buf: Uint8Array): this;

  /**
   * Finalizes hash and returns digest
   * @returns Hash digest as Uint8Array
   */
  digest(): Uint8Array;

  /**
   * Finalizes hash and writes digest to provided buffer
   * @param out - Output buffer (must be >= outputLen)
   */
  digestInto(out: Uint8Array): void;

  /**
   * Destroys internal state (zeros memory)
   */
  destroy(): void;

  /**
   * Creates independent copy of current hash state
   * @returns Cloned hash instance
   */
  clone(): T;
}

Usage Examples

BLAKE2 as a MAC

import { blake2b } from '@noble/hashes/blake2.js';

function createMAC(key: Uint8Array, message: Uint8Array): Uint8Array {
  return blake2b(message, { key, dkLen: 32 });
}

function verifyMAC(key: Uint8Array, message: Uint8Array, tag: Uint8Array): boolean {
  const computed = createMAC(key, message);

  if (computed.length !== tag.length) return false;

  let diff = 0;
  for (let i = 0; i < computed.length; i++) {
    diff |= computed[i] ^ tag[i];
  }
  return diff === 0;
}

const key = new Uint8Array(32).fill(0x42);
const message = new Uint8Array([1, 2, 3, 4]);
const tag = createMAC(key, message);
const valid = verifyMAC(key, message, tag);

BLAKE3 Key Derivation

import { blake3 } from '@noble/hashes/blake3.js';
import { utf8ToBytes } from '@noble/hashes/utils.js';

function deriveKey(
  masterKey: Uint8Array,
  context: string,
  keyLen: number
): Uint8Array {
  // Convert context string to Uint8Array
  // This is required because context MUST be Uint8Array, not string
  return blake3(masterKey, {
    context: utf8ToBytes(context),
    dkLen: keyLen
  });
}

const masterKey = new Uint8Array(32).fill(0x42);

// Derive different keys for different purposes
const encryptionKey = deriveKey(masterKey, 'encryption-key-v1', 32);
const authKey = deriveKey(masterKey, 'authentication-key-v1', 32);
const signingKey = deriveKey(masterKey, 'signing-key-v1', 32);

// All keys are cryptographically independent

Incremental Hashing with BLAKE2

import { blake2b } from '@noble/hashes/blake2.js';

async function hashLargeFile(fileChunks: Uint8Array[]): Promise<Uint8Array> {
  const hasher = blake2b.create({ dkLen: 32 });

  for (const chunk of fileChunks) {
    hasher.update(chunk);
  }

  return hasher.digest();
}

BLAKE3 Tree Hashing for Parallel Processing

import { blake3 } from '@noble/hashes/blake3.js';

// BLAKE3 internally uses tree hashing, which allows for parallelization
// In JavaScript (single-threaded), this still benefits from better CPU cache usage
function hashLargeData(data: Uint8Array): Uint8Array {
  return blake3(data, { dkLen: 32 });
}

// For truly parallel hashing, you would need Web Workers or similar

BLAKE2 with Domain Separation

import { blake2b } from '@noble/hashes/blake2.js';
import { utf8ToBytes } from '@noble/hashes/utils.js';

function domainSeparatedHash(
  data: Uint8Array,
  domain: string
): Uint8Array {
  // Convert domain string to bytes and pad/truncate to exactly 16 bytes
  // This is required because personalization MUST be Uint8Array of exactly 16 bytes
  const domainBytes = utf8ToBytes(domain);
  const personalization = new Uint8Array(16);
  personalization.set(domainBytes.slice(0, 16));

  return blake2b(data, {
    personalization,
    dkLen: 32
  });
}

// Different domains produce different hashes
const hash1 = domainSeparatedHash(data, 'email-verify');
const hash2 = domainSeparatedHash(data, 'password-hash');

Technical Details

BLAKE1 Specifications

  • Based on ChaCha stream cipher structure
  • Uses 32-bit (blake224/256) or 64-bit (blake384/512) operations
  • 14 or 16 rounds of processing
  • Rarely used in practice, included for compatibility

BLAKE2 Specifications

  • Improved performance over BLAKE1
  • BLAKE2b: 64-bit operations, optimized for 64-bit platforms, up to 64-byte output
  • BLAKE2s: 32-bit operations, optimized for 8-32 bit platforms, up to 32-byte output
  • 12 rounds for BLAKE2b, 10 rounds for BLAKE2s
  • Supports keyed mode for MAC without HMAC construction
  • Supports salt and personalization for domain separation

BLAKE3 Specifications

  • Even faster than BLAKE2
  • Uses tree hashing structure for parallelization
  • 7 rounds (fewer than BLAKE2 but different structure)
  • Fixed 32-byte default output, unlimited via XOF
  • Three modes: hash, keyed hash (MAC), key derivation
  • Supports incremental updates and seeking in output

Performance Characteristics

On Apple M4 for 32-byte input:

  • BLAKE2b: ~2μs per operation
  • BLAKE2s: ~1μs per operation
  • BLAKE3: ~1μs per operation

For 1MB input:

  • BLAKE2b: ~14ms
  • BLAKE2s: ~17ms
  • BLAKE3: ~13ms

BLAKE3 is fastest for large inputs due to tree structure.

Security Notes

  • BLAKE1: Considered secure but rarely used
  • BLAKE2: Provides same security as SHA-3 with better performance
  • BLAKE3: Security analysis ongoing, but designed by reputable cryptographers
  • All variants resistant to length extension attacks
  • BLAKE2 preferred over SHA-256 in many modern applications
  • BLAKE3 suitable for non-critical applications; use BLAKE2 for conservative security

When to Use Each

BLAKE1: Only for compatibility with legacy systems

BLAKE2b:

  • General-purpose hashing on 64-bit platforms
  • When you need better performance than SHA-2
  • MAC without HMAC overhead
  • Domain separation via personalization

BLAKE2s:

  • Embedded systems and 32-bit platforms
  • When you need compact implementation
  • IoT devices with limited resources

BLAKE3:

  • Highest performance requirements
  • File integrity checking
  • Content-addressed storage
  • Key derivation with context
  • When you need tree hashing structure
  • XOF/variable-length output

Advantages Over Other Hashes

vs SHA-2:

  • Faster (especially BLAKE3)
  • Simpler to implement keyed hashing
  • Built-in personalization support

vs SHA-3:

  • Significantly faster
  • Better suited for high-performance applications
  • More efficient on modern CPUs

vs MD5/SHA-1:

  • Secure (unlike MD5/SHA-1)
  • Similar or better performance
  • Modern design with better security margins

References

  • BLAKE1 Paper: Original BLAKE specification
  • RFC 7693: BLAKE2 Specification
  • BLAKE3 Website: BLAKE3 specifications and paper
  • BLAKE2 Website: BLAKE2 information and test vectors

Install with Tessl CLI

npx tessl i tessl/npm-noble--hashes

docs

argon2.md

blake.md

eskdf.md

hkdf.md

hmac.md

index.md

legacy.md

pbkdf2.md

scrypt.md

sha2.md

sha3-addons.md

sha3.md

utils.md

webcrypto.md

tile.json