cybersecurity · intermediate · ~30 min
Combine character-class scanning with a numeric checksum.
Implement void redact_cards(char *line) that mutates line in place, replacing every run of digits whose length is in [13, 19] AND that passes the Luhn checksum with the literal text [redacted].
The Luhn check, briefly:
You only redact runs of plain digits. Spaces or dashes between digits do not extend the run for this exercise.
"card 4532015112830366 in log"
-> "card [redacted] in log" // Luhn-valid 16 digits
"old 1234567890123456 is invalid"
-> "old 1234567890123456 is invalid" // 16 digits, but Luhn-invalid
"ten digits 1234567890 leave alone"
-> "ten digits 1234567890 leave alone" // too short
"long 12345678901234567890 leave alone"
-> "long 12345678901234567890 leave alone" // 20 digits, too long
PCI-DSS compliance requires masking primary account numbers (PANs) in logs and exports. The pragmatic check is: any run of 13–19 digits that passes the Luhn checksum is treated as a card number and redacted.
Mutable null-terminated line.
line mutated in place.
No allocations beyond a local scratch buffer.
void redact_cards(char *line) { /* TODO */ }
Forgetting the length window (13..19). Doubling the wrong digit (it's every second from the right, not the left).
Digit run too short; too long; valid Luhn but not in window; multiple cards in one line.
O(strlen(line) * avg-digit-run-length).
Solve this exercise in the browser editor — compile and run against the test harness, no setup required.