From 4ce7860a1995e46a007672e030d0c7bebfacc5b7 Mon Sep 17 00:00:00 2001 From: J8k3 Date: Sat, 23 May 2026 10:23:41 -0400 Subject: [PATCH] fix(dukpt): add KSN/BDK to JSON output for AES and TDES DUKPT derive operations AES DUKPT IK JSON was missing ksn, iki, counter; working key was missing ksn. TDES DUKPT IPEK and session key JSON were missing ksn and bdk. Both now mirror the full derivation context, making json=true self-contained for debugging and cross-validation. Co-Authored-By: Claude Sonnet 4.6 --- src/core/operations/DeriveDUKPTAESKey.mjs | 5 +++-- src/core/operations/DeriveDUKPTKey.mjs | 6 +++++- tests/operations/tests/Payment.mjs | 2 ++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/core/operations/DeriveDUKPTAESKey.mjs b/src/core/operations/DeriveDUKPTAESKey.mjs index 737c55d9..8d798df9 100644 --- a/src/core/operations/DeriveDUKPTAESKey.mjs +++ b/src/core/operations/DeriveDUKPTAESKey.mjs @@ -305,8 +305,9 @@ class DeriveDUKPTAESKey extends Operation { if (deriveMode === "Initial Key (IK)") { if (outputJson) { - const out = { inputKeyType, ik: hex(ik) }; + const out = { inputKeyType, ksn: hex(ksn), iki: hex(iki), counter: `0x${counter.toString(16).padStart(8, "0").toUpperCase()}` }; if (inputKeyType === "BDK") out.bdk = hex(inputKey); + out.ik = hex(ik); return JSON.stringify(out, null, 4); } return hex(ik); @@ -317,7 +318,7 @@ class DeriveDUKPTAESKey extends Operation { const wkKey = deriveWorkingKey(txKey, iki, counter, purpose); if (outputJson) { - const out = { inputKeyType, iki: hex(iki), counter: `0x${counter.toString(16).padStart(8, "0").toUpperCase()}` }; + const out = { inputKeyType, ksn: hex(ksn), iki: hex(iki), counter: `0x${counter.toString(16).padStart(8, "0").toUpperCase()}` }; if (inputKeyType === "BDK") out.bdk = hex(inputKey); out.ik = hex(ik); out.transactionKey = hex(txKey); diff --git a/src/core/operations/DeriveDUKPTKey.mjs b/src/core/operations/DeriveDUKPTKey.mjs index 20a54315..8f1ec8f2 100644 --- a/src/core/operations/DeriveDUKPTKey.mjs +++ b/src/core/operations/DeriveDUKPTKey.mjs @@ -253,9 +253,11 @@ class DeriveDUKPTKey extends Operation { const ipek = deriveIpek(bdk, ksn); const ipekHex = toHexFast(ipek).toUpperCase(); + const ksnHexOut = toHexFast(ksn).toUpperCase(); + if (mode === "Derive IPEK") { if (outputJson) { - return JSON.stringify({ mode, ipek: ipekHex }, null, 4); + return JSON.stringify({ mode, ksn: ksnHexOut, bdk: toHexFast(bdk).toUpperCase(), ipek: ipekHex }, null, 4); } return ipekHex; } @@ -267,6 +269,8 @@ class DeriveDUKPTKey extends Operation { if (outputJson) { return JSON.stringify({ mode, + ksn: ksnHexOut, + bdk: toHexFast(bdk).toUpperCase(), ipek: ipekHex, sessionBase: toHexFast(sessionBase).toUpperCase(), variant, diff --git a/tests/operations/tests/Payment.mjs b/tests/operations/tests/Payment.mjs index a95d350a..b4a553f4 100644 --- a/tests/operations/tests/Payment.mjs +++ b/tests/operations/tests/Payment.mjs @@ -482,6 +482,8 @@ TestRegister.addTests([ input: "0123456789ABCDEFFEDCBA9876543210", expectedOutput: JSON.stringify({ mode: "Derive Session Key", + ksn: "FFFF9876543210E00001", + bdk: "0123456789ABCDEFFEDCBA9876543210", ipek: "6AC292FAA1315B4D858AB3A3D7D5933A", sessionBase: "042666B49184CFA368DE9628D0397BC9", variant: "None",