PAYMENT_RECIPES.md was duplicating content now maintained in
J8k3/CyberChef-Payments (recipe catalog, chaining patterns, validation
status). Trimmed to: naming conventions, operation registry, raw APC
comparison test vectors + results. Added pointer to CyberChef-Payments.
AGENTS.md updated:
- Pre-commit checklist now says: update PAYMENT_RECIPES.md operation
registry + CyberChef-Payments README if op appears in catalog
- Added paragraph clarifying the two-file split (dev vs. user-facing)
- Naming convention step now explicitly calls out CyberChef-Payments
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Update opening: workflow-oriented tooling for engineering, debugging,
interoperability, development, QA — replaces narrow regulated-env framing
- Add explicit links to CyberChef-Payments (workflow catalog) and Payments (KB)
near the top
- Replace verbose recipe list (24 entries) with 7 representative examples;
redirect to J8k3/CyberChef-Payments for the full catalog and screenshots
- Fix typo: "Current coverage includes:h" -> "Current coverage includes:"
- Rewrite validation section: remove "unfinished product" and "best validation
we can do" — replace with scoped statement on standards, vectors, and APC
comparison where APIs are comparable
- Restructure: What this fork adds / Scope / Validation / Non-goals / Recipes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Domain prefix must come first per AGENTS.md convention. All references
updated: op file, Categories.json, tests, PAYMENT_RECIPES.md, lib comment.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
eslint:tests catches Payment.mjs too — document that npx grunt eslint runs
all five targets, not just eslint:core.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
11 ESLint errors across 6 files introduced in the ARQC/ARPC/TLV/Script ops.
Also document the constructor-JSDoc and operator-linebreak rules in AGENTS.md
to prevent recurrence.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The one-way rule (CyberChef gaps → GitHub issue) didn't cover the return path.
New paragraph: discoveries from CyberChef sessions (PCI rules, algorithm edge cases,
HSM commands) must be written back into the MCP server in the same session.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Also fixes expectedError test format (OperationErrors surface as result
strings, not result.error) and updates PAYMENT_RECIPES.md docs.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
XOR key ceremony helpers: split a key into 2-8 components and recombine.
Chains cleanly with Key Generate and wrap/encrypt operations.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- AGENTS.md: add APC cross-reference, security constraint, ESLint, and gap-filing instructions
- PAYMENT_RECIPES.md: DUKPT AES key status to Externally cross-checked; VISA PVV APC results updated with second key cross-check
- README.md: PIN Block Translate Encrypted in coverage list and recipe links
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
X9.24-3 uses AES_Encrypt_ECB for all derivation steps, not AES-CMAC.
Intermediate tree nodes use key usage 0x8000 (not 0x0000), and the
binary tree traversal must cover all 32 counter bits (not 21).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
decimalizePvv() was using a single-pass that immediately mapped A-F to
0-5. The Visa PVV spec (matching ANSI X9.8 and jPOS behavior) requires
two-pass: collect all decimal digits (0-9) first; only then re-scan
mapping A=0 B=1 C=2 D=3 E=4 F=5. This matches decimalizeCvvHex() which
was already correct. Bug produced wrong PVV whenever a hex letter appeared
before the first decimal digit in the encrypted output.
Test vectors updated from "6077" (single-pass result) to "6776" (correct
two-pass result) for the encrypted PVV hex 6A77E65CFE349D60.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
README:
- Added DUKPT AES key derivation to current coverage (ANSI X9.24-3, 12-byte KSN, AES-128)
- Expanded DUKPT TDES line to include standard/KSN details for clarity
- Removed AES DUKPT from Future extensions (it shipped)
PAYMENT_RECIPES:
- Replaced "deprecated" with "removed" for Translate Payment PIN Data (issue #4 was resolved)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
AGENTS.md:
- Added npm start (dev server), npm run build (prod), and NODE_OPTIONS heap-size tip from upstream Getting-started wiki
Card Validation Data Generate/Verify:
- Added Profile behaviour note to both descriptions: CVV2 forces service code 000, iCVV forces 999, the arg is ignored for those profiles
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- PIN Data Verify: add Output as JSON toggle (was always returning JSON with no way to get plain boolean; all other verify ops have this toggle)
- EMV Verify MAC: fix inlineHelp to say "session integrity key" (was "session key", inconsistent with arg name and description body)
- DUKPT Derive TDES Key: replace stale "AES DUKPT not implemented" note with pointer to DUKPT Derive AES Key operation
- EMV Generate MAC (PIN Change): replace "Emulation helper" / "This emulation" with "Test helper" / "This operation" throughout description, inlineHelp, and arg comment
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
PVV Verify, IBM 3624 Verify PIN, and EMV Verify ARQC all previously took
the long preimage data as input and the short cryptogram/offset as an arg,
which broke natural recipe chaining from their Generate counterparts.
Swapped each: the short output (PVV, offset, ARQC) now flows in as input;
the preimage/PIN data moves to an arg. Also added an Output as JSON toggle
to EMV Verify ARQC for consistency with other verify operations.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Both HSM Parse Thales Command and HSM Parse Futurex Command parse
message framing and field structure only; they do not interpret,
validate, or execute command payloads. Added a prominent Scope note
to this.description and this.inlineHelp on both operations so users
see the limitation before relying on the output for semantic analysis.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The per-bit loop was setting the FULL counter value on every hit instead
of OR-ing in one bit at a time. For any counter with more than one set
bit the two calls to nonReversibleKeyGen received the same ksnReg and
produced wrong derived keys. The existing test vector used counter 0x08
(one set bit), which masked the bug.
Fix: accumulate bits with |= so ksnReg grows one bit per iteration:
ksnReg[7] |= (bit >> 16) & 0x1F
ksnReg[8] |= (bit >> 8) & 0xFF
ksnReg[9] |= bit & 0xFF
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- CalculatePaymentKCV: fix HMAC SHA-224 using SHA-512/224 (forge.md.sha512.sha224)
instead of standard SHA-224 (now uses "sha224" string, consistent with other HMAC methods)
- PaymentMac: collapse 3-clause DUKPT variant ternary to single expression; the
ISO 9797-1 fallback to "MAC Request" was already correct and is now explicit
- AGENTS.md: renumber steps 1-7 sequentially; add step 6 — review and update
this.description/inlineHelp/testDataSamples whenever changing a recipe
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Two bugs in generateBrandPan:
1. For networks with multiple prefix rules, always picked the same rule
(Mastercard always 2-series, AmEx always 37, Discover always 6011)
2. Always used the start of the range as the prefix, so Mastercard
generated 51xxxxx or 2221xxxxxx every time instead of any value
in 51-55 or 2221-2720
Fix both: pick a random prefix rule and a random prefix within start..end.
Add a "Mastercard series" arg to PAN Generate so callers can explicitly
request 5-series (51-55), 2-series (2221-2720), or leave it random.
The curated sample path is unaffected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Rename two ops to follow the domain-prefix-first convention:
"Parse TR-31 Key Block" -> "TR-31 Parse Key Block"
"Parse TR-34 Key Transport" -> "TR-34 Parse Key Transport"
Sort all 33 Payments category entries alphabetically in Categories.json.
With domain-prefix names the prefixes cluster related ops naturally, so
alphabetical order is also logical order.
Update PAYMENT_RECIPES.md UI Arrangement section to document alphabetical
ordering. Fix stale lowercase references in AWS_PAYMENT_CRYPTOGRAPHY_RECIPES.md.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After the op-rename batch, the runtime threw 'f[e.module][e.name] is not
a constructor' for every renamed op because Payment.mjs and index.mjs are
gitignored generated files that were never regenerated after this.name
was updated.
Add a rule to AGENTS.md step 6 naming the three generated files, the
symptom of a stale registry, and the two-command fix.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace six static inputs that held hardcoded keys or PINs with the
appropriate __RANDOM_*__ placeholder so the populate button delivers a
fresh value each time rather than a fixed test vector:
- PIN Data Generate, IBM 3624 Generate PIN Offset, VISA PVV Generate
→ __RANDOM_PIN_4__
- DUKPT Derive TDES Key, AS2805 Generate KEK Validation
→ __RANDOM_TDES_16_HEX__
- DUKPT Derive AES Key → __RANDOM_AES_128_HEX__
Add a recipeConfig chain sample to two ops where the output of
Key Generate flows directly into the next op as input:
- Card Validation Data Generate: Key Generate → Card Validation Data Generate
- Payment Calculate KCV: Key Generate → Payment Calculate KCV
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>