Chapter 11 — Cryptography and trust services: verification
Lesson map
Lesson 11 published. Map, example, EX041.
flowchart TD
N0["Learning outcomes"]
N1["11.1 Test vectors"]
N2["11.2 Verifying callbacks"]
N3["Lab — HMAC test vector and callback check"]
N4["11.3 What passing proves"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5
N5 --> EX["Worked example"]
EX --> Q["Exercise EX041"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["11.1 Test vectors"]
N2["11.2 Verifying callbacks"]
N3["Lab — HMAC test vector and callback check"]
N4["11.3 What passing proves"]
N5["Synthesis"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> Q["EX041"]
[Learning outcomes]
|
v
[11.1 Test vectors]
|
v
[11.2 Verifying callbacks]
|
v
[Lab — HMAC test vector and callback check]
|
v
[11.3 What passing proves]
|
v
[Synthesis]
|
v
[Worked example] --> [Exercise EX041]
Learning outcomes
You will (1) verify an implementation against a published test vector; (2) verify message authentication with constant-time comparison; (3) state what a passing test does and does not prove.
11.1 Test vectors
Before trusting any cryptographic component, Lumen checks it against published test vectors: fixed inputs with known correct outputs, printed in standards. RFC 4231 lists vectors for HMAC-SHA-256. If Python's hmac module, a vendor appliance or a partner's library produces the documented output for those inputs, Tomás gains confidence that the algorithm is wired correctly. A mismatch means something is wrong, perhaps the wrong hash function or a key encoding error. Test vectors check correctness of the primitive; they do not prove that keys are protected or that the surrounding protocol is safe.
11.2 Verifying callbacks
The payment processor signs each callback with HMAC-SHA-256 using a secret shared with Lumen. The portal recomputes the HMAC over the received body and compares it with the header. Tomás learns two rules. First, compare with hmac.compare_digest, which takes the same time whether the first or last byte differs, rather than with ==, which can leak timing. Second, include a timestamp in the signed data and reject old messages, so an attacker cannot replay a captured callback. The lab checks the RFC 4231 vector and then verifies an authentic, a modified and a stale synthetic callback.
Lab — HMAC test vector and callback check
# HMAC-SHA-256: RFC 4231 test case 1, then synthetic callback checks. Teaching only.
import hmac, hashlib
key = bytes.fromhex("0b" * 20); data = b"Hi There"
expected = "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7"
print("RFC 4231 TC1 match:", hmac.new(key, data, hashlib.sha256).hexdigest() == expected)
SECRET = b"synthetic-callback-secret"; NOW = 1_800_000_000; WINDOW = 300
def sign(ts, body): return hmac.new(SECRET, f"{ts}.".encode() + body, hashlib.sha256).hexdigest()
def verify(ts, body, tag):
return abs(NOW - ts) <= WINDOW and hmac.compare_digest(sign(ts, body), tag)
body = b'{"order":"LF-1042","status":"paid"}'
tag = sign(NOW - 20, body)
print("authentic:", verify(NOW - 20, body, tag))
print("edited body:", verify(NOW - 20, body.replace(b"paid", b"refunded"), tag))
old = NOW - 3600
print("stale replay:", verify(old, body, sign(old, body)))
Run with python3 lab_hmac.py. Verified output:
RFC 4231 TC1 match: True
authentic: True
edited body: False
stale replay: False
11.3 What passing proves
A green test is easy to over-read. Passing the RFC 4231 vector proves the HMAC computation is correct for that input. Passing the callback test proves the portal rejects one tampered body and one stale timestamp. It does not prove the shared secret is stored safely, that every code path calls the check, or that the processor's own systems are secure. Tomás writes each verification result with its limits stated, so managers do not read a single passing check as a statement that payments are secure end to end.
Worked example
Tomás runs the HMAC lab, sees the vector match, the edited callback fail and the stale callback fail, and records the result with its stated limits.
Synthetic case. The callback secret and bodies are synthetic; RFC 4231 test case 1 is real.
Errors and limits
Test vectors do not cover side channels or key handling. A replay window that is too long weakens the timestamp check.
Exercises
- EX041 — Vector purpose. What does matching an RFC 4231 vector prove? Rubric: 3 = the HMAC computation is correct for those inputs, not key safety or protocol safety;; 2 = correctness;; 1 = security overall;; 0 = none.
- EX042 — compare_digest reason. Why use hmac.compare_digest instead of ==? Rubric: 3 = constant-time comparison avoids timing leaks of how many bytes match;; 2 = timing;; 1 = no difference;; 0 = none.
- EX043 — Stale callback. In the lab, why was the third callback rejected although its tag was valid? Rubric: 3 = its timestamp was older than the 300 s window, so it was treated as a replay;; 2 = timestamp;; 1 = tag wrong;; 0 = none.
- EX044 — Reporting limits. Name one thing the passing callback test does not prove. Rubric: 3 = secret storage, all code paths calling the check, or provider security;; 2 = one item;; 1 = proves all;; 0 = none.
Synthesis
Verification combines published vectors, correct comparison and replay checks, and is reported together with what it leaves unproven.
Continue studying — chapter 11 of 18
← Chapter 10 (draft) · Course chapter index · Chapter 12 (draft) →