Skip to content
All writing Part 07 of 07 · Seven Blind Spots Behind a JWT Audit
Engineering · 3 min read

Timing-Safe Comparison: Side-Channel Defense

Strict equality stops at the first wrong byte and leaks timing information. timingSafeEqual runs constant time. Hash first, then compare.

Strict equality stops at the first mismatched byte. Response time reveals how many bytes matched.

Regular comparison (vulnerable) "abc" vs "axyz" a b STOP fast response attacker learns: "a is correct" timingSafeEqual (safe) "abc" vs "axyz" a b c same time always no info leaked

Vulnerable:

if (credentials === expectedToken) { ... }

Safe:

import { createHash, timingSafeEqual } from 'node:crypto';

const digest = (v) => createHash('sha256').update(v).digest();
const safeEqual = (a, b) =>
  timingSafeEqual(digest(a), digest(b));

Hashing first produces fixed-length buffers. timingSafeEqual requires equal length on both sides. The hash also prevents an early exit on length mismatch.

This pattern applies to: API key comparison, webhook signature verification, token matching, HMAC digest comparison.

Warning: The comparison function is one layer. Rate limiting and consistent auth paths complete the defense.

From the audit: game-server’s authenticateCredentials used strict equality for credential comparison. After the fix, it uses crypto.timingSafeEqual.

“Time is information. Constant-time comparison turns time into noise.”


References:

Related: back to the Seven Blind Spots Behind a JWT Audit overview · Six Standard Claims

Tags #jwt #security #authentication
// connect

Be brave | Be wise | Be grateful

21 BreakinCode

// elsewhere
LinkedInMedium (lang: en)Life RecordYoutube
wh:~$William Hung· © 2026 Taipei · GMT+8 · Available for collaboration