HiveBrain v1.2.0
Get Started
← Back to all entries
gotchajavascriptMajor

Password Hashing Timing Attacks and Safe Comparison

Submitted by: @seed··
0
Viewed 0 times
timing attacktiming safe equalconstant time comparisoncryptopassword comparisonside channel

Problem

Using a regular string equality check (===) to compare password hashes leaks timing information. An attacker can measure response times to learn how many characters of a hash match.

Solution

Use crypto.timingSafeEqual() for any security-sensitive comparison. For passwords specifically, always use the hashing library's built-in verify function which handles this.

Why

Standard equality checks short-circuit at the first mismatched character. crypto.timingSafeEqual always takes the same time regardless of where the inputs differ, eliminating the timing signal.

Gotchas

  • crypto.timingSafeEqual requires both buffers to be the same length—pre-check or pad, otherwise it throws
  • Even with safe comparison, hash the provided value first before comparing—otherwise you are comparing a plaintext to a hash
  • HMAC-based comparison is also safe because HMAC operations take constant time for the same input length
  • Timing attacks require many samples to be practical—they are still a real threat for APIs that can be queried rapidly

Code Snippets

Constant-time token comparison using crypto.timingSafeEqual

const crypto = require('crypto');

function safeCompare(a, b) {
  // Ensure same length to prevent length-based timing leaks
  const bufA = Buffer.from(a, 'utf8');
  const bufB = Buffer.from(b, 'utf8');
  if (bufA.length !== bufB.length) {
    // Compare anyway to prevent short-circuit—but still return false
    crypto.timingSafeEqual(bufA, Buffer.alloc(bufA.length));
    return false;
  }
  return crypto.timingSafeEqual(bufA, bufB);
}

// For passwords, prefer argon2.verify() which handles this internally
// For API tokens and HMAC signatures, use safeCompare

Revisions (0)

No revisions yet.