security-constant-time-analysis
Constant-Time Analysis
When to Use
- Reviewing code that compares secrets (tokens, passwords, MACs, signatures)
- Auditing cryptographic implementations for timing leaks
- Checking authentication or authorization code for side-channel risks
- Verifying that branching doesn't depend on secret values
- Analyzing code paths that process sensitive data with variable timing
When NOT to Use
- Non-security-sensitive comparisons (public data)
- Performance optimization (different goal)
- General code review without cryptographic context
Why Timing Matters
Non-constant-time string comparison reveals information bit by bit:
# VULNERABLE: Early exit leaks prefix length
def check_token(provided, expected):
if len(provided) != len(expected):
return False
for a, b in zip(provided, expected):
if a != b:
return False # Exits early - timing reveals match position
return True
An attacker can measure response times to determine how many characters match, then brute-force one character at a time.
Safe Patterns by Language
Python
import hmac
# SAFE: constant-time comparison
hmac.compare_digest(provided_token, expected_token)
# Also safe for bytes
hmac.compare_digest(provided_hash, expected_hash)
Node.js
const crypto = require('crypto');
// SAFE: constant-time comparison
crypto.timingSafeEqual(
Buffer.from(provided),
Buffer.from(expected)
);
Go
import "crypto/subtle"
// SAFE: constant-time comparison
subtle.ConstantTimeCompare([]byte(provided), []byte(expected))
Rust
use subtle::ConstantTimeEq;
// SAFE: constant-time comparison
provided.ct_eq(&expected).into()
Detection Patterns
# Find potentially unsafe secret comparisons
grep -rn "==.*token\|==.*secret\|==.*password\|==.*api_key" --include="*.py" --include="*.js" --include="*.ts" .
# Find safe comparison usage
grep -rn "compare_digest\|timingSafeEqual\|ConstantTimeCompare\|ct_eq" .
Vulnerable Code Patterns
| Pattern | Language | Risk |
|---|---|---|
if token == expected: |
Python | Timing leak |
if (token === expected) |
JavaScript | Timing leak |
strings.Compare(a, b) |
Go | Timing leak |
token.equals(expected) |
Java | Timing leak |
bcrypt.compare(a, b) |
Any | Safe (bcrypt is constant-time) |
Beyond String Comparison
Timing leaks can also occur in:
- Conditional branches on secret values (if/else based on key bits)
- Array indexing with secret indices (cache timing)
- Early returns in validation functions
- Database lookups that vary by existence (user enumeration)
- Regular expressions with backtracking on secret data
Mitigation Strategies
- Use language-provided constant-time comparison functions
- Avoid branching on secret values
- Use constant-time select operations instead of if/else
- Add artificial delays to normalize response times (last resort)
- Use hash-then-compare for variable-length secrets
More from elizaos/eliza
nano-pdf
Edits PDF files using natural-language instructions via the nano-pdf CLI. Supports modifying text, changing titles, fixing typos, and updating content on specific pages. Use when the user wants to edit a PDF, modify PDF content, update PDF text, fix a typo in a PDF, change a PDF title, or rewrite part of a PDF page.
30wacli
Send WhatsApp messages to other people or search/sync WhatsApp history via the wacli CLI (not for normal user chats). Use when the user asks to send a WhatsApp message, text someone on WhatsApp, search WhatsApp chat history, sync WhatsApp conversations, backfill message history, or forward a file via WhatsApp to a third party.
27nano-banana-pro
Generate or edit images via Gemini 3 Pro Image (Nano Banana Pro). Use when the user asks to create an image, generate a picture, produce AI-generated artwork, edit a photo, compose multiple images, or upscale an image to higher resolution. Supports text-to-image generation, single-image editing, and multi-image composition using the Gemini API.
27obsidian
Work with Obsidian vaults (plain Markdown notes) and automate via obsidian-cli. Use when the user asks about notes, vault management, PKM, knowledge base organization, wikilinks, or personal knowledge management in Obsidian.
25session-logs
Search and analyze session logs (older/parent conversations) stored as JSONL files using jq and rg. Use when the user asks about prior chats, previous conversations, conversation history, what was said before, session costs, token usage, or tool usage breakdown across past sessions.
24discord
Use when you need to control Discord from Otto via the discord tool: send messages, react, post or upload stickers, upload emojis, run polls, manage threads/pins/search, create/edit/delete channels and categories, fetch permissions or member/role/channel info, set bot presence/activity, or handle moderation actions in Discord DMs or channels.
24