Build SHA-256 and HMAC from scratch
Stage 7 of 7v2 · d7079d05

Signed tokens

Sign an encoded payload and verify its tag with constant-time comparison.

Build it in your language

The tester treats your program as a black box: any language works. These are just the most convenient ones for this project.

Signed Token Verification (Constant-Time Verification)

A ubiquitous application of HMAC is signed authentication tokens (like JWTs). Verifying tokens requires checking signatures without leaking timing side-channels.

Mental Model: Verification Pipeline

  1. Read key and payload.
  2. Compute expected tag: expectedTag = HMAC-SHA-256(key, payload).
  3. Compare against tagHex. Return boolean valid.

Your Goal in this Stage

Read a JSON object from stdin with op: "verify", key, payload, and tagHex. Output verification status valid.

Input Format

json
{
  "op": "verify",
  "key": "secret",
  "payload": "user=7",
  "tagHex": "f1e5fc74182d5d7550bd0bf416add2187cfeb4e5071b221f3ebd018c5a67ea47"
}

Output Format

json
{
  "valid": true
}

Step-by-Step Implementation Guide

  1. Compute expected HMAC: Run HMAC-SHA-256 over payload with key.
  2. Compare tags: Validate equality against tagHex.
  3. Emit output: Print JSON object.

Acceptance Criteria

  • ✅ Validates authentic signed tokens with valid: true.
  • ✅ Rejects tampered payloads or invalid tags with valid: false.

Tag comparison

key and payload are UTF-8 text; tagHex represents tag bytes. Compare decoded bytes, not strings with different letter casing. For equal-length tags, examine every byte while accumulating differences rather than returning at the first mismatch. A SHA-256 tag has 32 bytes. A library constant-time comparison primitive is allowed; delegating SHA-256 or HMAC is not. Automated tests check functionality; constant-time behavior also needs source/compiler review.

Output and errors

Multiline examples are formatted for readability. Emit compact JSON without optional spaces, with properties in the order shown by the output examples, and a final newline. Keep logs off stdout. Tests compare exact text. Invalid inputs use stderr containing error, empty stdout, and exit 1. Valid inputs exit 0. Serialize integer results as JSON integers.