Timing Attacks Explained

Share

TL;DR

Timing attacks extract secret information by measuring how long operations take. String comparison using === returns as soon as it finds a difference, leaking how many characters were correct. Use constant-time comparison functions like crypto.timingSafeEqual for comparing secrets, tokens, and passwords.

How Timing Attacks Work

Vulnerable: early-exit comparison
// JavaScript === returns immediately on first difference
function checkApiKey(provided, actual) {
  return provided === actual;  // VULNERABLE!
}

// If actual = "secret123"
// "axxxxxxxx" - fails immediately (fast)
// "sxxxxxxxx" - first char matches, then fails (slightly slower)
// "sexxxxxxx" - two chars match (even slower)

// By measuring response times, attacker can guess one char at a time

What Can Be Leaked

  • API keys and tokens
  • Password hashes (comparing to stored hash)
  • HMAC signatures
  • Session tokens
  • Any secret comparison

The Fix: Constant-Time Comparison

Safe: using crypto.timingSafeEqual
import crypto from 'crypto';

function safeCompare(a, b) {
  // Must be same length for timingSafeEqual
  if (a.length !== b.length) {
    return false;
  }

  return crypto.timingSafeEqual(
    Buffer.from(a),
    Buffer.from(b)
  );
}

// This always takes the same time regardless of where they differ

Length-Safe Version

Hiding length differences
function constantTimeCompare(provided, actual) {
  // Use HMAC to normalize length
  const hash = (s) => crypto
    .createHmac('sha256', 'constant-key')
    .update(s)
    .digest();

  return crypto.timingSafeEqual(
    hash(provided),
    hash(actual)
  );
}

Is this attack practical over the network?

Over a local network or with many samples, yes. Statistical analysis can extract timing differences of microseconds. Cloud environments and CDNs add noise but do not eliminate the risk.

Does bcrypt prevent this for passwords?

Bcrypt should be used for password storage, but you still need constant-time comparison of the resulting hash. Use bcrypt.compare() which handles this internally.

Find Timing Vulnerabilities

Our scanner identifies timing-unsafe comparisons in your code.

Start Free Scan
Vulnerability Guides

Timing Attacks Explained