Fix DUKPT TDES counter accumulation in deriveSessionBaseKey

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>
This commit is contained in:
J8k3 2026-05-18 14:41:42 -04:00
parent 17cc3f9cb9
commit b345d5b8e9

View File

@ -175,9 +175,11 @@ function deriveSessionBaseKey(ipek, ksn) {
for (let shift = 20; shift >= 0; shift--) {
const bit = 1 << shift;
if ((counter & bit) !== 0) {
ksnReg[7] = (ksnReg[7] & 0xE0) | (((counter & 0x1F0000) >> 16) & 0x1F);
ksnReg[8] = (counter >> 8) & 0xFF;
ksnReg[9] = counter & 0xFF;
// Accumulate one bit at a time — setting the full counter here would
// repeat the same ksnReg on every hit and produce wrong derived keys.
ksnReg[7] |= (bit >> 16) & 0x1F;
ksnReg[8] |= (bit >> 8) & 0xFF;
ksnReg[9] |= bit & 0xFF;
curKey = nonReversibleKeyGen(curKey, ksnReg);
}
}