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

sha3-addons.mddocs/

SHA-3 Addons: Advanced Keccak Functions

Advanced Keccak-based cryptographic functions from NIST SP 800-185 and IETF drafts, including customizable SHAKE (cSHAKE), Keccak MAC (KMAC), TurboSHAKE, KangarooTwelve, TupleHash, ParallelHash, and a Keccak-based pseudo-random generator.

Imports

import {
  cshake128, cshake256,
  kmac128, kmac256, kmac128xof, kmac256xof,
  tuplehash128, tuplehash256, tuplehash128xof, tuplehash256xof,
  parallelhash128, parallelhash256, parallelhash128xof, parallelhash256xof,
  turboshake128, turboshake256,
  kt128, kt256,
  HopMAC128, HopMAC256,
  keccakprg
} from '@noble/hashes/sha3-addons.js';

Capabilities

cSHAKE: Customizable SHAKE

Customizable SHAKE allows domain separation through customization strings, preventing hash collisions between different protocol contexts.

/**
 * cSHAKE128 - Customizable SHAKE128
 * @param msg - Input data as Uint8Array
 * @param opts - Customization options
 * @param opts.personalization - Domain separation string
 * @param opts.NISTfn - NIST function name (string or Uint8Array)
 * @param opts.dkLen - Desired output length in bytes
 * @returns Hash digest of specified length
 */
function cshake128(msg: Uint8Array, opts?: cShakeOpts): Uint8Array;

// Properties
cshake128.outputLen: undefined; // Variable output length
cshake128.blockLen: 168;        // Block length in bytes

// Create incremental hasher
function create(opts?: cShakeOpts): Keccak;

/**
 * cSHAKE256 - Customizable SHAKE256
 * @param msg - Input data as Uint8Array
 * @param opts - Customization options
 * @param opts.personalization - Domain separation string
 * @param opts.NISTfn - NIST function name (string or Uint8Array)
 * @param opts.dkLen - Desired output length in bytes
 * @returns Hash digest of specified length
 */
function cshake256(msg: Uint8Array, opts?: cShakeOpts): Uint8Array;

// Properties
cshake256.outputLen: undefined; // Variable output length
cshake256.blockLen: 136;        // Block length in bytes

// Create incremental hasher
function create(opts?: cShakeOpts): Keccak;

/**
 * Options for cSHAKE functions
 */
interface cShakeOpts {
  /** Domain separation / personalization string */
  personalization?: Uint8Array;
  /** NIST function name for domain separation */
  NISTfn?: string | Uint8Array;
  /** Desired output length in bytes */
  dkLen?: number;
}

Usage:

import { cshake256 } from '@noble/hashes/sha3-addons.js';
import { utf8ToBytes } from '@noble/hashes/utils.js';

// Domain-separated hashing for different contexts
const emailHash = cshake256(data, {
  personalization: utf8ToBytes('email-verification'),
  dkLen: 32
});

const authHash = cshake256(data, {
  personalization: utf8ToBytes('authentication-token'),
  dkLen: 32
});

// These produce different outputs even for the same input

KMAC: Keccak Message Authentication Code

Keccak-based MAC that provides authentication with optional XOF mode.

/**
 * KMAC128 - 128-bit Keccak MAC
 * @param key - Secret key as Uint8Array
 * @param message - Message to authenticate as Uint8Array
 * @param opts - Options
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes (default: 32)
 * @returns MAC tag
 */
function kmac128(key: Uint8Array, message: Uint8Array, opts?: KMACOpts): Uint8Array;

// Create incremental MAC
function create(key: Uint8Array, opts?: KMACOpts): Keccak;

/**
 * KMAC256 - 256-bit Keccak MAC
 * @param key - Secret key as Uint8Array
 * @param message - Message to authenticate as Uint8Array
 * @param opts - Options
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes (default: 64)
 * @returns MAC tag
 */
function kmac256(key: Uint8Array, message: Uint8Array, opts?: KMACOpts): Uint8Array;

// Create incremental MAC
function create(key: Uint8Array, opts?: KMACOpts): Keccak;

/**
 * KMAC128 XOF - 128-bit Keccak MAC with extendable output
 * @param key - Secret key as Uint8Array
 * @param message - Message to authenticate as Uint8Array
 * @param opts - Options
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes
 * @returns MAC tag
 */
function kmac128xof(key: Uint8Array, message: Uint8Array, opts?: KMACOpts): Uint8Array;

// Create incremental MAC
function create(key: Uint8Array, opts?: KMACOpts): Keccak;

/**
 * KMAC256 XOF - 256-bit Keccak MAC with extendable output
 * @param key - Secret key as Uint8Array
 * @param message - Message to authenticate as Uint8Array
 * @param opts - Options
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes
 * @returns MAC tag
 */
function kmac256xof(key: Uint8Array, message: Uint8Array, opts?: KMACOpts): Uint8Array;

// Create incremental MAC
function create(key: Uint8Array, opts?: KMACOpts): Keccak;

/**
 * Options for KMAC functions
 */
interface KMACOpts {
  /** Domain separation / personalization string */
  personalization?: Uint8Array;
  /** Desired output length in bytes */
  dkLen?: number;
}

Usage:

import { kmac256 } from '@noble/hashes/sha3-addons.js';
import { utf8ToBytes } from '@noble/hashes/utils.js';

const key = new Uint8Array(32).fill(0x42);
const message = utf8ToBytes('Hello, World!');

// Simple MAC
const mac = kmac256(key, message);

// MAC with custom output length
const longMac = kmac256(key, message, { dkLen: 64 });

// MAC with domain separation
const authMac = kmac256(key, message, {
  personalization: utf8ToBytes('auth-v1'),
  dkLen: 32
});

// Incremental MAC
const macHasher = kmac256.create(key, { dkLen: 32 });
macHasher.update(chunk1);
macHasher.update(chunk2);
const result = macHasher.digest();

TupleHash: Unambiguous Tuple Hashing

TupleHash provides unambiguous hashing of tuples, ensuring that different tuple structures produce different hashes.

/**
 * TupleHash128 - 128-bit unambiguous tuple hashing
 * @param messages - Array of messages to hash
 * @param opts - Options
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes (default: 32)
 * @returns Hash digest
 */
function tuplehash128(messages: Uint8Array[], opts?: TupleHashOpts): Uint8Array;

// Create incremental hasher
function create(opts?: TupleHashOpts): TupleHashInstance;

/**
 * TupleHash256 - 256-bit unambiguous tuple hashing
 * @param messages - Array of messages to hash
 * @param opts - Options
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes (default: 64)
 * @returns Hash digest
 */
function tuplehash256(messages: Uint8Array[], opts?: TupleHashOpts): Uint8Array;

// Create incremental hasher
function create(opts?: TupleHashOpts): TupleHashInstance;

/**
 * TupleHash128 XOF - 128-bit tuple hashing with extendable output
 * @param messages - Array of messages to hash
 * @param opts - Options
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes
 * @returns Hash digest
 */
function tuplehash128xof(messages: Uint8Array[], opts?: TupleHashOpts): Uint8Array;

// Create incremental hasher
function create(opts?: TupleHashOpts): TupleHashInstance;

/**
 * TupleHash256 XOF - 256-bit tuple hashing with extendable output
 * @param messages - Array of messages to hash
 * @param opts - Options
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes
 * @returns Hash digest
 */
function tuplehash256xof(messages: Uint8Array[], opts?: TupleHashOpts): Uint8Array;

// Create incremental hasher
function create(opts?: TupleHashOpts): TupleHashInstance;

/**
 * Options for TupleHash functions
 */
interface TupleHashOpts {
  /** Domain separation / personalization string */
  personalization?: Uint8Array;
  /** Desired output length in bytes */
  dkLen?: number;
}

Usage:

import { tuplehash256 } from '@noble/hashes/sha3-addons.js';
import { utf8ToBytes } from '@noble/hashes/utils.js';

// Unambiguous tuple hashing
const tuple1 = [utf8ToBytes('ab'), utf8ToBytes('c')];
const tuple2 = [utf8ToBytes('a'), utf8ToBytes('bc')];

const hash1 = tuplehash256(tuple1);
const hash2 = tuplehash256(tuple2);
// hash1 !== hash2 even though concatenation is the same

// With personalization
const hash3 = tuplehash256(tuple1, {
  personalization: utf8ToBytes('my-protocol-v1')
});

ParallelHash: Parallel Hashing

ParallelHash enables parallel processing of large inputs (though JavaScript implementation is not actually parallel, it's included for compatibility).

/**
 * ParallelHash128 - 128-bit parallel hashing
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.blockLen - Block size for parallel processing (default: 8)
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes (default: 32)
 * @returns Hash digest
 */
function parallelhash128(msg: Uint8Array, opts?: ParallelOpts): Uint8Array;

// Create incremental hasher
function create(opts?: ParallelOpts): Keccak;

/**
 * ParallelHash256 - 256-bit parallel hashing
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.blockLen - Block size for parallel processing (default: 8)
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes (default: 64)
 * @returns Hash digest
 */
function parallelhash256(msg: Uint8Array, opts?: ParallelOpts): Uint8Array;

// Create incremental hasher
function create(opts?: ParallelOpts): Keccak;

/**
 * ParallelHash128 XOF - 128-bit parallel hashing with extendable output
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.blockLen - Block size for parallel processing
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes
 * @returns Hash digest
 */
function parallelhash128xof(msg: Uint8Array, opts?: ParallelOpts): Uint8Array;

// Create incremental hasher
function create(opts?: ParallelOpts): Keccak;

/**
 * ParallelHash256 XOF - 256-bit parallel hashing with extendable output
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.blockLen - Block size for parallel processing
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes
 * @returns Hash digest
 */
function parallelhash256xof(msg: Uint8Array, opts?: ParallelOpts): Uint8Array;

// Create incremental hasher
function create(opts?: ParallelOpts): Keccak;

/**
 * Options for ParallelHash functions
 */
interface ParallelOpts {
  /** Block size for parallel processing (in bytes) */
  blockLen?: number;
  /** Domain separation / personalization string */
  personalization?: Uint8Array;
  /** Desired output length in bytes */
  dkLen?: number;
}

Usage:

import { parallelhash256 } from '@noble/hashes/sha3-addons.js';
import { utf8ToBytes } from '@noble/hashes/utils.js';

const largeData = new Uint8Array(1024 * 1024); // 1MB

const hash = parallelhash256(largeData, {
  blockLen: 8192, // 8KB blocks
  dkLen: 32
});

TurboSHAKE: Reduced-Round Keccak

TurboSHAKE is a faster variant using 12 rounds instead of 24, trading some security margin for performance.

/**
 * TurboSHAKE128 - 12-round reduced Keccak (128-bit)
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.D - Domain separation byte (default: 0x1f)
 * @param opts.dkLen - Desired output length in bytes
 * @returns Hash digest
 */
function turboshake128(msg: Uint8Array, opts?: TurboshakeOpts): Uint8Array;

// Properties
turboshake128.outputLen: undefined; // Variable output length
turboshake128.blockLen: 168;        // Block length in bytes

// Create incremental hasher
function create(opts?: TurboshakeOpts): Keccak;

/**
 * TurboSHAKE256 - 12-round reduced Keccak (256-bit)
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.D - Domain separation byte (default: 0x1f)
 * @param opts.dkLen - Desired output length in bytes
 * @returns Hash digest
 */
function turboshake256(msg: Uint8Array, opts?: TurboshakeOpts): Uint8Array;

// Properties
turboshake256.outputLen: undefined; // Variable output length
turboshake256.blockLen: 136;        // Block length in bytes

// Create incremental hasher
function create(opts?: TurboshakeOpts): Keccak;

/**
 * Options for TurboSHAKE functions
 */
interface TurboshakeOpts {
  /** Domain separation byte (0x01-0x7f) */
  D?: number;
  /** Desired output length in bytes */
  dkLen?: number;
}

Usage:

import { turboshake256 } from '@noble/hashes/sha3-addons.js';

// Fast hashing with reduced rounds
const hash = turboshake256(data, { dkLen: 32 });

// With custom domain separation
const hash2 = turboshake256(data, {
  D: 0x05,
  dkLen: 64
});

KangarooTwelve (K12): Fast Keccak Variant

KangarooTwelve combines reduced rounds with a tree structure for very fast hashing.

/**
 * KangarooTwelve 128-bit (K12-128)
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes (default: 32)
 * @returns Hash digest
 */
function kt128(msg: Uint8Array, opts?: KangarooOpts): Uint8Array;

// Properties
kt128.outputLen: 32;     // Default output length in bytes
kt128.blockLen: undefined; // Variable block length

// Create incremental hasher
function create(opts?: KangarooOpts): _KangarooTwelve;

/**
 * KangarooTwelve 256-bit (K12-256)
 * @param msg - Input data as Uint8Array
 * @param opts - Options
 * @param opts.personalization - Domain separation string
 * @param opts.dkLen - Desired output length in bytes (default: 64)
 * @returns Hash digest
 */
function kt256(msg: Uint8Array, opts?: KangarooOpts): Uint8Array;

// Properties
kt256.outputLen: 64;     // Default output length in bytes
kt256.blockLen: undefined; // Variable block length

// Create incremental hasher
function create(opts?: KangarooOpts): _KangarooTwelve;

/**
 * Options for KangarooTwelve functions
 */
interface KangarooOpts {
  /** Domain separation / personalization string */
  personalization?: Uint8Array;
  /** Desired output length in bytes */
  dkLen?: number;
}

/**
 * HopMAC128 - KangarooTwelve-based MAC (128-bit)
 * @param key - Secret key as Uint8Array
 * @param message - Message to authenticate as Uint8Array
 * @param personalization - Optional domain separation string
 * @param dkLen - Desired output length in bytes (default: 32)
 * @returns MAC tag
 */
function HopMAC128(
  key: Uint8Array,
  message: Uint8Array,
  personalization?: Uint8Array,
  dkLen?: number
): Uint8Array;

/**
 * HopMAC256 - KangarooTwelve-based MAC (256-bit)
 * @param key - Secret key as Uint8Array
 * @param message - Message to authenticate as Uint8Array
 * @param personalization - Optional domain separation string
 * @param dkLen - Desired output length in bytes (default: 64)
 * @returns MAC tag
 */
function HopMAC256(
  key: Uint8Array,
  message: Uint8Array,
  personalization?: Uint8Array,
  dkLen?: number
): Uint8Array;

Usage:

import { kt128, HopMAC128 } from '@noble/hashes/sha3-addons.js';
import { utf8ToBytes } from '@noble/hashes/utils.js';

// Fast hashing
const hash = kt128(largeData, { dkLen: 32 });

// With personalization
const hash2 = kt128(data, {
  personalization: utf8ToBytes('app-v1'),
  dkLen: 32
});

// MAC using HopMAC
const key = new Uint8Array(32).fill(0x42);
const message = utf8ToBytes('authenticate this');
const mac = HopMAC128(key, message);

Keccak PRG: Pseudo-Random Generator

Keccak-based pseudo-random generator for generating cryptographically secure random bytes.

/**
 * Creates a Keccak-based pseudo-random generator
 * @param capacity - Security capacity in bits (default: 254 for 128-bit security)
 * @returns PRG instance
 */
function keccakprg(capacity?: number): _KeccakPRG;

/**
 * Keccak PRG instance
 */
class _KeccakPRG {
  /**
   * Adds entropy to the PRG state
   * @param seed - Entropy source as Uint8Array
   */
  addEntropy(seed: Uint8Array): void;

  /**
   * Generates random bytes
   * @param length - Number of bytes to generate
   * @returns Cryptographically secure random bytes
   */
  randomBytes(length: number): Uint8Array;

  /**
   * Clears internal state
   */
  clean(): void;
}

Usage:

import { keccakprg } from '@noble/hashes/sha3-addons.js';
import { randomBytes } from '@noble/hashes/utils.js';

// Create PRG with 254-bit capacity (128-bit security)
const prg = keccakprg(254);

// Add initial entropy
prg.addEntropy(randomBytes(32));

// Generate random bytes
const random1 = prg.randomBytes(32);
const random2 = prg.randomBytes(64);
const random3 = prg.randomBytes(16);

// Add more entropy periodically
prg.addEntropy(randomBytes(32));

// Clean up when done
prg.clean();

Usage Examples

Domain-Separated Key Derivation

import { cshake256 } from '@noble/hashes/sha3-addons.js';
import { utf8ToBytes } from '@noble/hashes/utils.js';

function deriveKey(
  masterKey: Uint8Array,
  context: string,
  keyId: number,
  keyLen: number
): Uint8Array {
  const hasher = cshake256.create({
    personalization: utf8ToBytes(`${context}-v1`),
    dkLen: keyLen
  });

  hasher.update(masterKey);
  hasher.update(new Uint8Array([keyId]));

  return hasher.digest();
}

const masterKey = new Uint8Array(32).fill(0x42);
const encKey = deriveKey(masterKey, 'encryption', 1, 32);
const authKey = deriveKey(masterKey, 'authentication', 2, 32);

Authenticated Encryption with KMAC

import { kmac256 } from '@noble/hashes/sha3-addons.js';
import { utf8ToBytes, concatBytes } from '@noble/hashes/utils.js';

function encryptAndAuthenticate(
  key: Uint8Array,
  plaintext: Uint8Array,
  nonce: Uint8Array
): { ciphertext: Uint8Array; tag: Uint8Array } {
  // Derive encryption key
  const encKey = kmac256(key, concatBytes(utf8ToBytes('enc'), nonce), { dkLen: 32 });

  // XOR encryption (for demonstration - use proper cipher in production)
  const ciphertext = plaintext.map((b, i) => b ^ encKey[i % 32]);

  // Generate authentication tag
  const tag = kmac256(key, concatBytes(nonce, ciphertext), {
    personalization: utf8ToBytes('auth'),
    dkLen: 32
  });

  return { ciphertext, tag };
}

Performance Optimization with TurboSHAKE

import { turboshake256 } from '@noble/hashes/sha3-addons.js';

function fastHash(data: Uint8Array): Uint8Array {
  // Use TurboSHAKE for non-critical hashing where speed matters
  return turboshake256(data, { dkLen: 32 });
}

function criticalHash(data: Uint8Array): Uint8Array {
  // Use standard SHA3-256 for security-critical operations
  return sha3_256(data);
}

Technical Details

NIST SP 800-185 Compliance

cSHAKE, KMAC, TupleHash, and ParallelHash conform to NIST SP 800-185 specifications.

Security Levels

  • 128-bit variants: Provide 128-bit security strength
  • 256-bit variants: Provide 256-bit security strength
  • TurboSHAKE/K12: Reduced security margin for performance

When to Use Each

cSHAKE: Domain separation, custom hash functions KMAC: Message authentication, keyed hashing TupleHash: Unambiguous tuple/list hashing ParallelHash: Large data hashing (compatibility) TurboSHAKE: Fast hashing with acceptable security KangarooTwelve: Very fast hashing for large data KeccakPRG: Deterministic random generation

Performance Notes

  • TurboSHAKE and K12 are approximately 2x faster than standard SHA-3
  • KMAC is comparable to HMAC but with better security properties
  • ParallelHash offers no performance benefit in JavaScript (single-threaded)

References

  • NIST SP 800-185: SHA-3 Derived Functions
  • KangarooTwelve Draft: K12 Specification
  • KeccakPRG: Pseudo-random generator specification

Install with Tessl CLI

npx tessl i tessl/npm-noble--hashes@2.0.0

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