Swap input/arg on all Verify operations for recipe chaining
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>
This commit is contained in:
parent
cb0f535aec
commit
a312c23fbc
@ -18,13 +18,13 @@ class VerifyEMVARQC extends Operation {
|
||||
|
||||
this.name = "EMV Verify ARQC";
|
||||
this.module = "Payment";
|
||||
this.description = "Paste the already-assembled EMV authorization-request input into the input field as hex and verify an AES-CMAC-based ARQC.<br><br><b>Input:</b> preassembled ARQC input data as hex.<br><b>Arguments:</b> provide the EMV session key, cryptogram length, and expected ARQC hex value.<br><br><b>Validation:</b> Partially verified. This checks the same supplied-key AES-CMAC EMV profile as generation and does not claim full scheme-level ARQC validation semantics.<br><br><b>Session key derivation:</b> In a full EMV flow the session key is derived from the issuer master key using the Application Transaction Counter (ATC) and PAN sequence number. Visa and Amex use EMV Common Session Key Derivation (Option A); Mastercard uses a different derivation (Option B). This operation expects you to supply the already-derived session key.<br><br><b>Security:</b> Clear session keys are test-use only.";
|
||||
this.inlineHelp = "<strong>Input:</strong> preassembled ARQC data as hex.<br><strong>Args:</strong> provide the AES session key and expected ARQC.<br><strong>Validation:</strong> same supplied-key EMV profile as generation.";
|
||||
this.description = "Paste the stored ARQC into the input field and verify it against an AES-CMAC recomputed from the preimage data.<br><br><b>Input:</b> stored ARQC cryptogram as hex (typically 8 bytes = 16 hex chars).<br><b>Arguments:</b> provide the EMV session key, cryptogram length, the preassembled ARQC input data, and choose output format.<br><br>This operation recomputes the ARQC from the supplied preimage and key, then compares it to the input ARQC. Use this directly after <b>EMV Generate ARQC</b> in a recipe — the ARQC output flows naturally into this input.<br><br><b>Validation:</b> Partially verified. This checks the same supplied-key AES-CMAC EMV profile as generation and does not claim full scheme-level ARQC validation semantics.<br><br><b>Session key derivation:</b> In a full EMV flow the session key is derived from the issuer master key using the Application Transaction Counter (ATC) and PAN sequence number. Visa and Amex use EMV Common Session Key Derivation (Option A); Mastercard uses a different derivation (Option B). This operation expects you to supply the already-derived session key.<br><br><b>Security:</b> Clear session keys are test-use only.";
|
||||
this.inlineHelp = "<strong>Input:</strong> stored ARQC cryptogram as hex.<br><strong>Args:</strong> provide the AES session key, preimage data, and cryptogram length.<br><strong>Validation:</strong> same supplied-key EMV profile as generation.";
|
||||
this.testDataSamples = [
|
||||
{
|
||||
name: "AES-CMAC ARQC verification sample",
|
||||
input: "000102030405060708090A0B0C0D0E0F",
|
||||
args: ["00112233445566778899AABBCCDDEEFF", 8, "C1F732B52FB20CAA"]
|
||||
input: "C1F732B52FB20CAA",
|
||||
args: ["00112233445566778899AABBCCDDEEFF", 8, "000102030405060708090A0B0C0D0E0F", true]
|
||||
}
|
||||
];
|
||||
this.infoURL = "https://en.wikipedia.org/wiki/EMV";
|
||||
@ -33,7 +33,8 @@ class VerifyEMVARQC extends Operation {
|
||||
this.args = [
|
||||
{ name: "Session key (hex)", type: "string", value: "", comment: "Provide the already-derived EMV session key as hex. This wrapper does not derive EMV session keys." },
|
||||
{ name: "Cryptogram bytes", type: "number", value: 8, min: 1, max: 16, comment: "Number of leftmost CMAC bytes to compare." },
|
||||
{ name: "Expected ARQC (hex)", type: "string", value: "", comment: "Expected ARQC value as hex." },
|
||||
{ name: "Preimage data (hex)", type: "string", value: "", comment: "Preassembled ARQC input data as hex — the same data used by EMV Generate ARQC to produce the ARQC." },
|
||||
{ name: "Output as JSON", type: "boolean", value: true, comment: "When enabled, returns the recomputed ARQC and validity result." },
|
||||
];
|
||||
}
|
||||
|
||||
@ -43,14 +44,15 @@ class VerifyEMVARQC extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [sessionKeyHex, cryptogramBytes, expectedArqc] = args;
|
||||
const generated = generateEmvAesCmacCryptogram(input, sessionKeyHex, cryptogramBytes);
|
||||
const normalizedExpected = (expectedArqc || "").replace(/\s+/g, "").toUpperCase();
|
||||
return JSON.stringify({
|
||||
const [sessionKeyHex, cryptogramBytes, preimage, outputJson] = args;
|
||||
const generated = generateEmvAesCmacCryptogram(preimage, sessionKeyHex, cryptogramBytes);
|
||||
const normalizedInput = (input || "").replace(/\s+/g, "").toUpperCase();
|
||||
const result = {
|
||||
...generated,
|
||||
expectedArqcHex: normalizedExpected,
|
||||
valid: generated.cryptogramHex === normalizedExpected
|
||||
}, null, 4);
|
||||
expectedArqcHex: normalizedInput,
|
||||
valid: generated.cryptogramHex === normalizedInput
|
||||
};
|
||||
return outputJson ? JSON.stringify(result, null, 4) : String(result.valid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -18,13 +18,13 @@ class VerifyIBM3624PIN extends Operation {
|
||||
|
||||
this.name = "IBM 3624 Verify PIN";
|
||||
this.module = "Payment";
|
||||
this.description = "Paste the clear PIN into the input field and verify it against an IBM 3624 offset.<br><br><b>Input:</b> clear PIN digits.<br><b>Arguments:</b> provide the clear PVK in hex, decimalization table, validation data, pad character, and expected offset.<br><br><b>Validation:</b> Partially verified. This is the verification pair for the same clear-key IBM 3624 helper logic used by generation.<br><br><b>Security:</b> Clear PIN and PVK material are test-use only.";
|
||||
this.inlineHelp = "<strong>Input:</strong> clear PIN digits.<br><strong>Args:</strong> provide PVK, decimalization table, validation data, pad character, and expected offset.<br><strong>Validation:</strong> clear-key IBM 3624 verification helper.";
|
||||
this.description = "Paste the stored PIN offset into the input field and verify it against a clear PIN.<br><br><b>Input:</b> stored IBM 3624 PIN offset (4 to 12 decimal digits).<br><b>Arguments:</b> provide the clear PVK in hex, decimalization table, validation data, pad character, and the clear PIN to verify.<br><br>This operation re-derives the offset from the supplied PIN and keying material and compares it to the input offset. Use this directly after <b>IBM 3624 Generate PIN Offset</b> in a recipe — the offset output flows naturally into this input.<br><br><b>Validation:</b> Partially verified. This is the verification pair for the same clear-key IBM 3624 helper logic used by generation.<br><br><b>Security:</b> Clear PIN and PVK material are test-use only.";
|
||||
this.inlineHelp = "<strong>Input:</strong> stored IBM 3624 PIN offset.<br><strong>Args:</strong> provide PVK, decimalization table, validation data, pad character, and the clear PIN to verify.<br><strong>Validation:</strong> clear-key IBM 3624 verification helper.";
|
||||
this.testDataSamples = [
|
||||
{
|
||||
name: "IBM 3624 verify sample",
|
||||
input: "1234",
|
||||
args: ["0123456789ABCDEFFEDCBA9876543210", "0123456789012345", "5432101234567890", "F", "3207", true]
|
||||
input: "3207",
|
||||
args: ["0123456789ABCDEFFEDCBA9876543210", "0123456789012345", "5432101234567890", "F", "1234", true]
|
||||
}
|
||||
];
|
||||
this.infoURL = "https://en.wikipedia.org/wiki/IBM_3624";
|
||||
@ -35,7 +35,7 @@ class VerifyIBM3624PIN extends Operation {
|
||||
{ name: "Decimalization table", type: "string", value: "0123456789012345", comment: "Sixteen decimal digits used to map hex nibbles to decimal digits." },
|
||||
{ name: "PIN validation data", type: "string", value: "", comment: "Issuer validation data, typically PAN-derived digits, 4 to 16 digits." },
|
||||
{ name: "Pad character", type: "shortString", value: "F", comment: "Single hex nibble used to right-pad validation data to 16 nibbles." },
|
||||
{ name: "PIN offset", type: "string", value: "", comment: "Stored IBM 3624 offset value to compare against." },
|
||||
{ name: "Clear PIN", type: "string", value: "", comment: "The PIN to verify. The operation re-derives the offset from this PIN and compares it to the input offset." },
|
||||
{ name: "Output as JSON", type: "boolean", value: true, comment: "When enabled, returns the recomputed offset and validity result." },
|
||||
];
|
||||
}
|
||||
@ -46,8 +46,8 @@ class VerifyIBM3624PIN extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [pvkHex, decimalizationTable, pinValidationData, padCharacter, pinOffset, outputJson] = args;
|
||||
const result = verifyIbm3624Pin(pvkHex, decimalizationTable, pinValidationData, padCharacter, pinOffset, input);
|
||||
const [pvkHex, decimalizationTable, pinValidationData, padCharacter, pin, outputJson] = args;
|
||||
const result = verifyIbm3624Pin(pvkHex, decimalizationTable, pinValidationData, padCharacter, input, pin);
|
||||
return outputJson ? JSON.stringify(result, null, 4) : String(result.valid);
|
||||
}
|
||||
}
|
||||
|
||||
@ -18,13 +18,13 @@ class VerifyVISAPVV extends Operation {
|
||||
|
||||
this.name = "VISA PVV Verify";
|
||||
this.module = "Payment";
|
||||
this.description = "Paste the clear PIN into the input field and verify it against a VISA PVV.<br><br><b>Input:</b> clear PIN digits.<br><b>Arguments:</b> provide the clear PVK in hex, PAN, PVKI, and expected PVV.<br><br><b>Validation:</b> Partially verified. This is the verification pair for the same clear-key VISA PVV helper logic used by generation.<br><br><b>Security:</b> Clear PIN and PVK material are test-use only.";
|
||||
this.inlineHelp = "<strong>Input:</strong> clear PIN digits.<br><strong>Args:</strong> provide PVK, PAN, PVKI, and expected PVV.<br><strong>Validation:</strong> clear-key VISA PVV verification helper.";
|
||||
this.description = "Paste the stored PVV into the input field and verify it against a clear PIN.<br><br><b>Input:</b> stored PVV (4 decimal digits).<br><b>Arguments:</b> provide the clear PVK in hex, PAN, PVKI, and the clear PIN to verify.<br><br>This operation re-derives the PVV from the supplied PIN and keying material and compares it to the input PVV. Use this directly after <b>VISA PVV Generate</b> in a recipe — the PVV output flows naturally into this input.<br><br><b>Validation:</b> Partially verified. This is the verification pair for the same clear-key VISA PVV helper logic used by generation.<br><br><b>Security:</b> Clear PIN and PVK material are test-use only.";
|
||||
this.inlineHelp = "<strong>Input:</strong> stored PVV (4 decimal digits).<br><strong>Args:</strong> provide PVK, PAN, PVKI, and the clear PIN to verify.<br><strong>Validation:</strong> clear-key VISA PVV verification helper.";
|
||||
this.testDataSamples = [
|
||||
{
|
||||
name: "VISA PVV verify sample",
|
||||
input: "1234",
|
||||
args: ["0123456789ABCDEFFEDCBA9876543210", "5432101234567890", 1, "6077", true]
|
||||
input: "6077",
|
||||
args: ["0123456789ABCDEFFEDCBA9876543210", "5432101234567890", 1, "1234", true]
|
||||
}
|
||||
];
|
||||
this.infoURL = "https://en.wikipedia.org/wiki/ISO_9564";
|
||||
@ -34,7 +34,7 @@ class VerifyVISAPVV extends Operation {
|
||||
{ name: "PIN verification key (hex)", type: "string", value: "", comment: "Provide the clear VISA PVK as 16-byte or 24-byte hex." },
|
||||
{ name: "Primary account number", type: "string", value: "", comment: "Provide the PAN as digits only. The standard PVV input uses the rightmost 11 digits before the check digit." },
|
||||
{ name: "PVKI", type: "number", value: 1, min: 0, max: 6, comment: "PIN verification key index from 0 through 6." },
|
||||
{ name: "Expected PVV", type: "string", value: "", comment: "Stored PVV value to compare against." },
|
||||
{ name: "Clear PIN", type: "string", value: "", comment: "The PIN to verify. The operation re-derives the PVV from this PIN and compares it to the input PVV." },
|
||||
{ name: "Output as JSON", type: "boolean", value: true, comment: "When enabled, returns the assembled PVV input and validity result." },
|
||||
];
|
||||
}
|
||||
@ -45,8 +45,8 @@ class VerifyVISAPVV extends Operation {
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [pvkHex, pan, pvki, expectedPvv, outputJson] = args;
|
||||
const result = verifyVisaPvv(pvkHex, pan, pvki, input, expectedPvv);
|
||||
const [pvkHex, pan, pvki, pin, outputJson] = args;
|
||||
const result = verifyVisaPvv(pvkHex, pan, pvki, pin, input);
|
||||
return outputJson ? JSON.stringify(result, null, 4) : String(result.valid);
|
||||
}
|
||||
}
|
||||
|
||||
@ -507,7 +507,7 @@ TestRegister.addTests([
|
||||
},
|
||||
{
|
||||
name: "EMV Verify ARQC: AES-CMAC profile",
|
||||
input: "000102030405060708090A0B0C0D0E0F",
|
||||
input: "C1F732B52FB20CAA",
|
||||
expectedOutput: JSON.stringify({
|
||||
inputHex: "000102030405060708090A0B0C0D0E0F",
|
||||
outputBytes: 8,
|
||||
@ -519,7 +519,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "EMV Verify ARQC",
|
||||
args: ["00112233445566778899AABBCCDDEEFF", 8, "C1F732B52FB20CAA"]
|
||||
args: ["00112233445566778899AABBCCDDEEFF", 8, "000102030405060708090A0B0C0D0E0F", true]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -720,7 +720,7 @@ TestRegister.addTests([
|
||||
},
|
||||
{
|
||||
name: "IBM 3624 Verify PIN: known sample",
|
||||
input: "1234",
|
||||
input: "3207",
|
||||
expectedOutput: JSON.stringify({
|
||||
pinVerificationKeyHex: "0123456789ABCDEFFEDCBA9876543210",
|
||||
pinValidationData: "5432101234567890",
|
||||
@ -738,7 +738,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "IBM 3624 Verify PIN",
|
||||
args: ["0123456789ABCDEFFEDCBA9876543210", "0123456789012345", "5432101234567890", "F", "3207", true]
|
||||
args: ["0123456789ABCDEFFEDCBA9876543210", "0123456789012345", "5432101234567890", "F", "1234", true]
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -763,7 +763,7 @@ TestRegister.addTests([
|
||||
},
|
||||
{
|
||||
name: "VISA PVV Verify: known sample",
|
||||
input: "1234",
|
||||
input: "6077",
|
||||
expectedOutput: JSON.stringify({
|
||||
pinVerificationKeyHex: "0123456789ABCDEFFEDCBA9876543210",
|
||||
pan: "5432101234567890",
|
||||
@ -778,7 +778,7 @@ TestRegister.addTests([
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "VISA PVV Verify",
|
||||
args: ["0123456789ABCDEFFEDCBA9876543210", "5432101234567890", 1, "6077", true]
|
||||
args: ["0123456789ABCDEFFEDCBA9876543210", "5432101234567890", 1, "1234", true]
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user