HMAC-DRBG Security-Focused API Documentation

Algorithm: HMAC-DRBG (Deterministic Random Bit Generator)
Type: Pseudorandom Number Generator
Security Level: Based on underlying hash (SHA-256: 128-bit)
Specification: NIST SP 800-90A Rev. 1

Security Contract

hmacDrbg.create(entropy: Uint8Array, personalization?: Uint8Array): HmacDrbg

Preconditions:

Postconditions:

Side Effects:

drbg.generate(length: number): Uint8Array

Preconditions:

Postconditions:

Side Effects:

Attack Resistance Matrix

Attack Type Resistance Notes
State Compromise ✅ Forward Secure Past outputs safe
Backtracking ✅ Strong Can’t compute previous
Prediction ✅ Strong Without state
Side-Channel ✅ Good HMAC is robust
Reseed Failure ⚠️ Degrades Need fresh entropy
State Cloning ❌ Vulnerable Must prevent
Quantum ⚠️ Reduced Hash security halved

Secure Usage Examples

✅ CORRECT: Nonce Generation

import { hmacDrbg } from 'metamui-hmac-drbg';

class NonceGenerator {
  private drbg: HmacDrbg;
  
  constructor(masterSeed: Uint8Array) {
    // Initialize with personalization
    this.drbg = hmacDrbg.create(
      masterSeed,
      stringToBytes("MyApp-Nonce-v1")
    );
  }
  
  // Generate unique nonces
  generateNonce(length: number = 16): Uint8Array {
    return this.drbg.generate(length);
  }
  
  // Reseed periodically
  reseed(additionalEntropy: Uint8Array): void {
    this.drbg.reseed(additionalEntropy);
  }
}

// Usage
const nonceGen = new NonceGenerator(deviceSecret);
const nonce1 = nonceGen.generateNonce(); // Unique
const nonce2 = nonceGen.generateNonce(); // Different

✅ CORRECT: Deterministic Key Derivation

import { hmacDrbg } from 'metamui-hmac-drbg';

// HD wallet key generation
class DeterministicKeyGen {
  private drbg: HmacDrbg;
  
  constructor(seed: Uint8Array, purpose: string) {
    this.drbg = hmacDrbg.create(
      seed,
      stringToBytes(`HDWallet-${purpose}`)
    );
  }
  
  deriveKey(index: number): Uint8Array {
    // Add index to additional input
    const additionalInput = new Uint8Array(4);
    new DataView(additionalInput.buffer).setUint32(0, index, false);
    
    return this.drbg.generateWithAdditional(
      32, // 256-bit key
      additionalInput
    );
  }
  
  // Derive multiple keys efficiently
  deriveKeys(count: number): Uint8Array[] {
    const keys: Uint8Array[] = [];
    
    for (let i = 0; i < count; i++) {
      keys.push(this.deriveKey(i));
    }
    
    return keys;
  }
}

✅ CORRECT: Session Key Rotation

import { hmacDrbg } from 'metamui-hmac-drbg';

class ForwardSecureSession {
  private drbg: HmacDrbg;
  private epoch: number = 0;
  
  constructor(sharedSecret: Uint8Array) {
    this.drbg = hmacDrbg.create(
      sharedSecret,
      stringToBytes("ForwardSecure-v1")
    );
  }
  
  // Get current epoch key
  getCurrentKey(): Uint8Array {
    return this.drbg.generateWithAdditional(
      32,
      encodeUint32(this.epoch)
    );
  }
  
  // Advance to next epoch (one-way)
  advance(): void {
    this.epoch++;
    
    // Optional: Reseed for extra security
    if (this.epoch % 1000 === 0) {
      const epochSeed = this.drbg.generate(32);
      this.drbg.reseed(epochSeed);
    }
  }
  
  // Cannot go backward (forward secure)
  getKeyForEpoch(epoch: number): Uint8Array | null {
    if (epoch < this.epoch) {
      return null; // Can't compute past keys
    }
    
    // Advance to requested epoch
    while (this.epoch < epoch) {
      this.advance();
    }
    
    return this.getCurrentKey();
  }
}

✅ CORRECT: Test Vector Generation

import { hmacDrbg } from 'metamui-hmac-drbg';

// Reproducible test vectors
function generateTestVectors(
  algorithm: string,
  count: number
): TestVector[] {
  // Fixed seed for reproducibility
  const seed = hexToBytes(
    "0123456789abcdef0123456789abcdef" +
    "0123456789abcdef0123456789abcdef"
  );
  
  const drbg = hmacDrbg.create(
    seed,
    stringToBytes(`TestVectors-${algorithm}`)
  );
  
  const vectors: TestVector[] = [];
  
  for (let i = 0; i < count; i++) {
    const input = drbg.generate(32);
    const key = drbg.generate(32);
    
    vectors.push({
      input: bytesToHex(input),
      key: bytesToHex(key),
      algorithm
    });
  }
  
  return vectors;
}

Common Mistakes to Avoid

❌ WRONG: Weak Entropy

// NEVER DO THIS - Predictable seed
const timestamp = Date.now();
const weakSeed = new Uint8Array(8);
new DataView(weakSeed.buffer).setBigUint64(0, BigInt(timestamp));
const drbg = hmacDrbg.create(weakSeed); // Only 64 bits!

// ✅ CORRECT: Use proper entropy
const strongSeed = crypto.getRandomValues(new Uint8Array(32));
const drbg = hmacDrbg.create(strongSeed); // 256 bits

❌ WRONG: State Cloning

// NEVER DO THIS - Cloning DRBG state
const drbg1 = hmacDrbg.create(seed);
const state = drbg1.exportState(); // If this existed
const drbg2 = hmacDrbg.importState(state); // Both generate same!

// ✅ CORRECT: Derive independent instances
const master = hmacDrbg.create(seed);
const seed1 = master.generate(32);
const seed2 = master.generate(32);
const drbg1 = hmacDrbg.create(seed1); // Independent
const drbg2 = hmacDrbg.create(seed2); // Different output

❌ WRONG: No Reseeding

// NEVER DO THIS - Never reseeding
const drbg = hmacDrbg.create(initialSeed);
// Generate millions of bytes without reseeding
for (let i = 0; i < 1000000; i++) {
  const data = drbg.generate(1024); // No fresh entropy
}

// ✅ CORRECT: Periodic reseeding
const drbg = hmacDrbg.create(initialSeed);
let generated = 0;

for (let i = 0; i < 1000000; i++) {
  const data = drbg.generate(1024);
  generated += 1024;
  
  // Reseed every 1MB
  if (generated >= 1024 * 1024) {
    const freshEntropy = crypto.getRandomValues(new Uint8Array(32));
    drbg.reseed(freshEntropy);
    generated = 0;
  }
}

Implementation Security

HMAC-DRBG Internals

class HmacDrbgImplementation {
  private V: Uint8Array;  // Internal state V
  private K: Uint8Array;  // HMAC key
  private reseedCounter: number;
  
  constructor(
    entropy: Uint8Array,
    personalization?: Uint8Array,
    nonce?: Uint8Array
  ) {
    // Initialize V and K
    this.V = new Uint8Array(32).fill(0x01);
    this.K = new Uint8Array(32).fill(0x00);
    
    // Instantiate with entropy
    const seedMaterial = concat(
      entropy,
      nonce || new Uint8Array(0),
      personalization || new Uint8Array(0)
    );
    
    this.update(seedMaterial);
    this.reseedCounter = 1;
  }
  
  private update(providedData?: Uint8Array): void {
    // K = HMAC(K, V || 0x00 || provided_data)
    const input = concat(
      this.V,
      new Uint8Array([0x00]),
      providedData || new Uint8Array(0)
    );
    
    this.K = hmac(this.K, input);
    
    // V = HMAC(K, V)
    this.V = hmac(this.K, this.V);
    
    if (providedData && providedData.length > 0) {
      // K = HMAC(K, V || 0x01 || provided_data)
      const input2 = concat(
        this.V,
        new Uint8Array([0x01]),
        providedData
      );
      
      this.K = hmac(this.K, input2);
      this.V = hmac(this.K, this.V);
    }
  }
  
  generate(length: number, additionalInput?: Uint8Array): Uint8Array {
    if (this.reseedCounter > RESEED_INTERVAL) {
      throw new Error("Reseed required");
    }
    
    if (additionalInput) {
      this.update(additionalInput);
    }
    
    // Generate output
    const output = new Uint8Array(length);
    let offset = 0;
    
    while (offset < length) {
      this.V = hmac(this.K, this.V);
      const copyLength = Math.min(32, length - offset);
      output.set(this.V.slice(0, copyLength), offset);
      offset += copyLength;
    }
    
    this.update(additionalInput);
    this.reseedCounter++;
    
    return output;
  }
}

Platform-Specific Notes

Performance

Comparison with Other DRBGs

Feature HMAC-DRBG CTR-DRBG Hash-DRBG
Speed Moderate Fast Slow
Security Proof Strong Strong Moderate
Side-Channel Good Needs AES-NI Good
Simplicity Simple Complex Simple

When to Use HMAC-DRBG

✅ Appropriate Uses:

❌ Inappropriate Uses:

Security Checklist

Security Analysis

Threat Model: HMAC-DRBG Threat Model

The comprehensive threat analysis covers:

For complete security analysis and risk assessment, see the dedicated threat model documentation.