Add payment MAC wrapper operations
This commit is contained in:
parent
7433b07f2b
commit
3f1b63378f
@ -25,8 +25,8 @@ Coverage legend:
|
||||
| `EncryptData` | `Direct` / `Partial` | Direct for AES, TDES, RSA. Partial for DUKPT and EMV-derived encryption. |
|
||||
| `DecryptData` | `Direct` / `Partial` | Direct for AES, TDES, RSA. Partial for DUKPT and EMV-derived decryption. |
|
||||
| `ReEncryptData` | `Direct` / `Partial` | Direct for plain decrypt-then-encrypt workflows. Partial for DUKPT re-encryption. |
|
||||
| `GenerateMac` | `Direct` / `Partial` | Direct for HMAC and CMAC. Partial for DUKPT MAC and EMV MAC flows. |
|
||||
| `VerifyMac` | `Direct` / `Partial` | Direct by recomputing and comparing HMAC/CMAC. Partial for DUKPT MAC and EMV MAC flows. |
|
||||
| `GenerateMac` | `Direct` / `Partial` | Direct for static-key HMAC and CMAC, and direct for the implemented DUKPT CMAC wrapper modes. Partial for ISO 9797, EMV MAC, and AS2805 flows. |
|
||||
| `VerifyMac` | `Direct` / `Partial` | Direct for static-key HMAC and CMAC, and direct for the implemented DUKPT CMAC wrapper modes. Partial for ISO 9797, EMV MAC, and AS2805 flows. |
|
||||
| `VerifyAuthRequestCryptogram` | `Partial` | Usable for AES-CMAC ARQC/ARPC-style checking when session key and preimage are already known. Dedicated ARQC and ARPC generators now exist for that constrained profile. |
|
||||
| `TranslateKeyMaterial` | `Partial` | Useful for ECDH derivation and TR-31 inspection, not full HSM-side rewrap semantics. |
|
||||
| `GenerateCardValidationData` | `Direct` | Direct for software CVV/CVV2/iCVV generation when the combined CVK pair is provided as clear hex. |
|
||||
@ -103,15 +103,29 @@ Suggested use:
|
||||
|
||||
## 6) AWS `VerifyMac`: Recompute And Compare
|
||||
Operations:
|
||||
- `From Hex`
|
||||
- `HMAC` or `CMAC`
|
||||
- `Take bytes`
|
||||
- `Verify payment MAC`
|
||||
|
||||
Suggested use:
|
||||
- Recompute the MAC using the same starter as `GenerateMac`.
|
||||
- Compare the result to the AWS `Mac` value manually or with a follow-on comparison recipe.
|
||||
- Paste the message into the input field, choose the MAC method, and provide either the direct key or the DUKPT BDK plus KSN.
|
||||
- Supply the expected MAC in hex and let the wrapper recompute and compare it.
|
||||
|
||||
## 7) AWS `GenerateCardValidationData`: CVV / CVV2 / iCVV
|
||||
Notes:
|
||||
- This covers the implemented static-key HMAC/CMAC and DUKPT-CMAC wrapper modes directly.
|
||||
- ISO 9797, EMV MAC, and AS2805-specific verification are still partial gaps.
|
||||
|
||||
## 7) AWS `GenerateMac`: Payment Wrapper
|
||||
Operations:
|
||||
- `Generate payment MAC`
|
||||
|
||||
Suggested use:
|
||||
- Paste the message into the input field and choose the payment MAC method that best matches the AWS attributes.
|
||||
- Use direct key input for static HMAC or CMAC modes, or provide a BDK plus KSN for the implemented DUKPT CMAC request and response modes.
|
||||
|
||||
Notes:
|
||||
- This wrapper exists for usability so payment users can stay in the `Payments` category without needing to know which low-level primitive is underneath.
|
||||
- It intentionally reuses the existing generic `HMAC` and `CMAC` implementations.
|
||||
|
||||
## 8) AWS `GenerateCardValidationData`: CVV / CVV2 / iCVV
|
||||
Operations:
|
||||
- `Generate card validation data`
|
||||
|
||||
@ -124,7 +138,7 @@ Notes:
|
||||
- This directly covers software generation of CVV/CVV2/iCVV-style values.
|
||||
- Assumption: CVV2 forces service code `000` and iCVV forces `999`.
|
||||
|
||||
## 8) AWS `VerifyCardValidationData`: CVV / CVV2 / iCVV
|
||||
## 9) AWS `VerifyCardValidationData`: CVV / CVV2 / iCVV
|
||||
Operations:
|
||||
- `Verify card validation data`
|
||||
|
||||
@ -138,7 +152,7 @@ Notes:
|
||||
|
||||
## Partial Recipe Starters
|
||||
|
||||
## 9) AWS `EncryptData` / `DecryptData`: DUKPT-Derived Symmetric Flows
|
||||
## 10) AWS `EncryptData` / `DecryptData`: DUKPT-Derived Symmetric Flows
|
||||
Operations:
|
||||
- `Derive DUKPT key`
|
||||
- `AES Encrypt` or `AES Decrypt` or `Triple DES Encrypt` or `Triple DES Decrypt`
|
||||
@ -151,20 +165,6 @@ Notes:
|
||||
- This is useful for offline vector work.
|
||||
- It does not claim one-to-one parity with every AWS DUKPT encryption attribute combination.
|
||||
|
||||
## 10) AWS `GenerateMac` / `VerifyMac`: DUKPT MAC
|
||||
Operations:
|
||||
- `Derive DUKPT key`
|
||||
- `From Hex`
|
||||
- `CMAC` or `HMAC`
|
||||
- `Take bytes`
|
||||
|
||||
Suggested use:
|
||||
- Derive the transaction key from BDK and KSN.
|
||||
- Convert `MessageData` from hex and generate the MAC using the derived key.
|
||||
|
||||
Notes:
|
||||
- Treat this as a lab starter, not proof of parity with AWS’s full DUKPT MAC union attributes.
|
||||
|
||||
## 11) AWS `VerifyAuthRequestCryptogram`: EMV ARQC Check
|
||||
Operations:
|
||||
- `Generate EMV ARQC`
|
||||
@ -257,6 +257,7 @@ Why:
|
||||
If you want closer AWS coverage, the highest-value missing operations are:
|
||||
1. PIN block encode/decode for ISO 9564 formats 0, 1, 3, and 4.
|
||||
2. IBM 3624 and VISA PVV generation and verification.
|
||||
3. Dedicated EMV MAC and profile-specific EMV session-derivation helpers.
|
||||
4. Clear-to-encrypted and encrypted-to-encrypted PIN translation flows.
|
||||
5. TR-31 unwrap and rewrap helpers for dynamic-key workflows.
|
||||
3. ISO 9797 and AS2805-specific MAC generation and verification.
|
||||
4. Dedicated EMV MAC and profile-specific EMV session-derivation helpers.
|
||||
5. Clear-to-encrypted and encrypted-to-encrypted PIN translation flows.
|
||||
6. TR-31 unwrap and rewrap helpers for dynamic-key workflows.
|
||||
|
||||
@ -62,7 +62,22 @@ Scope note:
|
||||
- CVV2 forces service code `000` and iCVV forces `999`.
|
||||
- It does not try to emulate scheme-specific dCVV, token CVV, or issuer-host formatting differences beyond the common decimalization flow.
|
||||
|
||||
## 8) EMV ARQC Generation (AES-CMAC Profile)
|
||||
## 8) Payment MAC Generation And Verification
|
||||
Operations:
|
||||
- `Generate payment MAC`
|
||||
- `Verify payment MAC`
|
||||
|
||||
Suggested use:
|
||||
- Paste the message data into the input field.
|
||||
- Choose whether the MAC should use static `HMAC`, static `CMAC`, or DUKPT-derived TDES-CMAC.
|
||||
- Provide either a direct MAC key or a BDK plus KSN, depending on the selected method.
|
||||
|
||||
Scope note:
|
||||
- This wrapper intentionally reuses the existing generic `HMAC` and `CMAC` implementations instead of duplicating crypto code.
|
||||
- Current DUKPT coverage derives TDES session keys and applies TDES-CMAC for request and response MAC variants.
|
||||
- ISO 9797, EMV session-derivation MAC, and AS2805 are still future additions.
|
||||
|
||||
## 9) EMV ARQC Generation (AES-CMAC Profile)
|
||||
Operations:
|
||||
- `Generate EMV ARQC`
|
||||
|
||||
@ -75,7 +90,7 @@ Scope note:
|
||||
- This operation is intentionally limited to AES-CMAC-style EMV profiles.
|
||||
- It does not derive EMV session keys or assemble CDOL/tag data for you.
|
||||
|
||||
## 9) EMV ARPC Generation (AES-CMAC Response Profile)
|
||||
## 10) EMV ARPC Generation (AES-CMAC Response Profile)
|
||||
Operations:
|
||||
- `Generate EMV ARPC`
|
||||
|
||||
@ -88,7 +103,7 @@ Scope note:
|
||||
- This operation is intentionally limited to AES-CMAC response profiles where the issuer session key and exact preimage are already known.
|
||||
- Legacy 3DES EMV ARQC/ARPC flows are not covered.
|
||||
|
||||
## 10) Combined Message Triage
|
||||
## 11) Combined Message Triage
|
||||
Operations:
|
||||
- `Parse TR-34 B9 envelope`
|
||||
- `Parse ASN.1 hex string`
|
||||
|
||||
@ -568,11 +568,21 @@
|
||||
{
|
||||
"name": "Payments",
|
||||
"ops": [
|
||||
"HMAC",
|
||||
"CMAC",
|
||||
"AES Encrypt",
|
||||
"AES Decrypt",
|
||||
"Triple DES Encrypt",
|
||||
"Triple DES Decrypt",
|
||||
"AES Key Wrap",
|
||||
"AES Key Unwrap",
|
||||
"Parse TR-31 key block",
|
||||
"Parse TR-34 B9 envelope",
|
||||
"Calculate payment KCV",
|
||||
"Derive ECDH key material",
|
||||
"Derive DUKPT key",
|
||||
"Generate payment MAC",
|
||||
"Verify payment MAC",
|
||||
"Generate card validation data",
|
||||
"Verify card validation data",
|
||||
"Generate EMV ARQC",
|
||||
|
||||
175
src/core/lib/PaymentMac.mjs
Normal file
175
src/core/lib/PaymentMac.mjs
Normal file
@ -0,0 +1,175 @@
|
||||
/**
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Utils from "../Utils.mjs";
|
||||
import OperationError from "../errors/OperationError.mjs";
|
||||
import HMAC from "../operations/HMAC.mjs";
|
||||
import CMAC from "../operations/CMAC.mjs";
|
||||
import DeriveDUKPTKey from "../operations/DeriveDUKPTKey.mjs";
|
||||
|
||||
const PAYMENT_MAC_METHODS = [
|
||||
"HMAC SHA-224",
|
||||
"HMAC SHA-256",
|
||||
"HMAC SHA-384",
|
||||
"HMAC SHA-512",
|
||||
"AES-CMAC",
|
||||
"TDES-CMAC",
|
||||
"DUKPT MAC Request CMAC",
|
||||
"DUKPT MAC Response CMAC",
|
||||
];
|
||||
|
||||
/**
|
||||
* Converts a string input into an ArrayBuffer according to the selected format.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {string} inputFormat
|
||||
* @returns {ArrayBuffer}
|
||||
*/
|
||||
function convertInputToBuffer(input, inputFormat) {
|
||||
const byteString = Utils.convertToByteString(input || "", inputFormat);
|
||||
return Utils.strToArrayBuffer(byteString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the effective MAC key for the selected method.
|
||||
*
|
||||
* @param {string} method
|
||||
* @param {Object} keySpec
|
||||
* @returns {{keyHex: string, keyContext: Object}}
|
||||
*/
|
||||
function resolveMacKey(method, keySpec) {
|
||||
const normalizedKey = (keySpec.keyValue || "").replace(/\s+/g, "");
|
||||
|
||||
if (method === "DUKPT MAC Request CMAC" || method === "DUKPT MAC Response CMAC") {
|
||||
if (keySpec.keyFormat !== "Hex") {
|
||||
throw new OperationError("DUKPT BDK must be provided in hex.");
|
||||
}
|
||||
if (!keySpec.ksn) {
|
||||
throw new OperationError("KSN is required for DUKPT MAC methods.");
|
||||
}
|
||||
|
||||
const variant = method === "DUKPT MAC Request CMAC" ? "MAC Request" : "MAC Response";
|
||||
const dukpt = new DeriveDUKPTKey();
|
||||
const keyHex = dukpt.run(normalizedKey, ["Derive Session Key", keySpec.ksn, variant, false]);
|
||||
|
||||
return {
|
||||
keyHex,
|
||||
keyContext: {
|
||||
keySource: "Derived from DUKPT BDK",
|
||||
ksn: keySpec.ksn.replace(/\s+/g, "").toUpperCase(),
|
||||
dukptVariant: variant
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const byteString = Utils.convertToByteString(keySpec.keyValue || "", keySpec.keyFormat);
|
||||
if (!byteString.length) {
|
||||
throw new OperationError("Key material is required.");
|
||||
}
|
||||
|
||||
return {
|
||||
keyHex: byteStringToHex(byteString),
|
||||
keyContext: {
|
||||
keySource: "Direct key input"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a byte string into uppercase hex.
|
||||
*
|
||||
* @param {string} byteString
|
||||
* @returns {string}
|
||||
*/
|
||||
function byteStringToHex(byteString) {
|
||||
return Array.from(byteString, ch => ch.charCodeAt(0).toString(16).padStart(2, "0")).join("").toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a payment MAC using the selected method.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {string} inputFormat
|
||||
* @param {string} method
|
||||
* @param {string} keyValue
|
||||
* @param {string} keyFormat
|
||||
* @param {string} ksn
|
||||
* @param {number} outputBytes
|
||||
* @returns {Object}
|
||||
*/
|
||||
function generatePaymentMac(input, inputFormat, method, keyValue, keyFormat, ksn, outputBytes) {
|
||||
const normalizedOutputBytes = Math.max(1, Number(outputBytes) || 8);
|
||||
const inputBuffer = convertInputToBuffer(input, inputFormat);
|
||||
const inputHex = byteStringToHex(Utils.arrayBufferToStr(inputBuffer, false));
|
||||
const { keyHex, keyContext } = resolveMacKey(method, { keyValue, keyFormat, ksn });
|
||||
|
||||
let fullMacHex;
|
||||
if (method.startsWith("HMAC ")) {
|
||||
const hmac = new HMAC();
|
||||
const hashName = {
|
||||
"HMAC SHA-224": "SHA224",
|
||||
"HMAC SHA-256": "SHA256",
|
||||
"HMAC SHA-384": "SHA384",
|
||||
"HMAC SHA-512": "SHA512",
|
||||
}[method];
|
||||
fullMacHex = hmac.run(inputBuffer, [{ string: keyHex, option: "Hex" }, hashName]).toUpperCase();
|
||||
} else {
|
||||
const cmac = new CMAC();
|
||||
const algorithm = method === "AES-CMAC" ? "AES" : "Triple DES";
|
||||
fullMacHex = cmac.run(inputBuffer, [{ string: keyHex, option: "Hex" }, algorithm]).toUpperCase();
|
||||
}
|
||||
|
||||
const macHex = fullMacHex.substring(0, normalizedOutputBytes * 2);
|
||||
|
||||
return {
|
||||
method,
|
||||
inputFormat,
|
||||
inputHex,
|
||||
outputBytes: normalizedOutputBytes,
|
||||
fullMacHex,
|
||||
macHex,
|
||||
...keyContext
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies a payment MAC by recomputing and comparing it.
|
||||
*
|
||||
* @param {string} input
|
||||
* @param {string} inputFormat
|
||||
* @param {string} method
|
||||
* @param {string} keyValue
|
||||
* @param {string} keyFormat
|
||||
* @param {string} ksn
|
||||
* @param {string} expectedMac
|
||||
* @returns {Object}
|
||||
*/
|
||||
function verifyPaymentMac(input, inputFormat, method, keyValue, keyFormat, ksn, expectedMac) {
|
||||
const normalizedExpected = (expectedMac || "").replace(/\s+/g, "").toUpperCase();
|
||||
if (!/^[0-9A-F]+$/.test(normalizedExpected) || normalizedExpected.length % 2 !== 0) {
|
||||
throw new OperationError("Expected MAC must be even-length hex.");
|
||||
}
|
||||
|
||||
const generated = generatePaymentMac(
|
||||
input,
|
||||
inputFormat,
|
||||
method,
|
||||
keyValue,
|
||||
keyFormat,
|
||||
ksn,
|
||||
normalizedExpected.length / 2
|
||||
);
|
||||
|
||||
return {
|
||||
...generated,
|
||||
expectedMacHex: normalizedExpected,
|
||||
valid: generated.macHex === normalizedExpected
|
||||
};
|
||||
}
|
||||
|
||||
export {
|
||||
PAYMENT_MAC_METHODS,
|
||||
generatePaymentMac,
|
||||
verifyPaymentMac,
|
||||
};
|
||||
93
src/core/operations/GeneratePaymentMAC.mjs
Normal file
93
src/core/operations/GeneratePaymentMAC.mjs
Normal file
@ -0,0 +1,93 @@
|
||||
/**
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import { PAYMENT_MAC_METHODS, generatePaymentMac } from "../lib/PaymentMac.mjs";
|
||||
|
||||
/**
|
||||
* Generate payment MAC operation.
|
||||
*/
|
||||
class GeneratePaymentMAC extends Operation {
|
||||
|
||||
/**
|
||||
* GeneratePaymentMAC constructor.
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Generate payment MAC";
|
||||
this.module = "Payment";
|
||||
this.description = "Paste the message data into the input field and generate a payment-oriented MAC using one payment-facing operation.<br><br><b>Input:</b> message data in the selected input format.<br><b>Arguments:</b> choose the MAC method, provide either a direct key or a DUKPT BDK, optionally provide a KSN for DUKPT methods, and choose the truncation length.<br><br>This wrapper reuses existing HMAC, CMAC, and DUKPT operations instead of duplicating their crypto logic.";
|
||||
this.inlineHelp = "<strong>Input:</strong> message data.<br><strong>Args:</strong> choose the payment MAC method, then provide either a direct key or a DUKPT BDK plus KSN.";
|
||||
this.testDataSamples = [
|
||||
{
|
||||
name: "Static AES-CMAC sample",
|
||||
input: "1122334455667788",
|
||||
args: ["Hex", "AES-CMAC", "00112233445566778899AABBCCDDEEFF", "Hex", "", 8, false]
|
||||
}
|
||||
];
|
||||
this.infoURL = "https://docs.aws.amazon.com/payment-cryptography/latest/DataAPIReference/API_GenerateMac.html";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Input format",
|
||||
type: "option",
|
||||
value: ["Hex", "UTF8", "Latin1", "Base64"],
|
||||
comment: "How to decode the input field before MAC generation. Use <code>Hex</code> for payment test vectors expressed as hex."
|
||||
},
|
||||
{
|
||||
name: "MAC method",
|
||||
type: "option",
|
||||
value: PAYMENT_MAC_METHODS,
|
||||
comment: "Static-key HMAC and CMAC modes reuse the existing generic primitives. DUKPT modes derive a TDES session key first and then apply TDES-CMAC."
|
||||
},
|
||||
{
|
||||
name: "Key / BDK",
|
||||
type: "string",
|
||||
value: "",
|
||||
comment: "Provide the direct MAC key for HMAC or CMAC methods, or the clear BDK for DUKPT methods."
|
||||
},
|
||||
{
|
||||
name: "Key format",
|
||||
type: "option",
|
||||
value: ["Hex", "UTF8", "Latin1", "Base64"],
|
||||
comment: "How to decode the key input. Assumption: DUKPT BDK input must be <code>Hex</code>."
|
||||
},
|
||||
{
|
||||
name: "KSN (DUKPT only)",
|
||||
type: "string",
|
||||
value: "",
|
||||
comment: "Required only for DUKPT MAC methods. Provide the full 10-byte KSN as 20 hex characters."
|
||||
},
|
||||
{
|
||||
name: "Output bytes",
|
||||
type: "number",
|
||||
value: 8,
|
||||
min: 1,
|
||||
max: 64,
|
||||
comment: "Number of leftmost MAC bytes to return. Leave at <code>8</code> for common payment truncation lengths."
|
||||
},
|
||||
{
|
||||
name: "Output as JSON",
|
||||
type: "boolean",
|
||||
value: false,
|
||||
comment: "When enabled, returns the full MAC, truncation details, and key-context metadata."
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [inputFormat, method, keyValue, keyFormat, ksn, outputBytes, outputJson] = args;
|
||||
const result = generatePaymentMac(input, inputFormat, method, keyValue, keyFormat, ksn, outputBytes);
|
||||
return outputJson ? JSON.stringify(result, null, 4) : result.macHex;
|
||||
}
|
||||
}
|
||||
|
||||
export default GeneratePaymentMAC;
|
||||
91
src/core/operations/VerifyPaymentMAC.mjs
Normal file
91
src/core/operations/VerifyPaymentMAC.mjs
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @license Apache-2.0
|
||||
*/
|
||||
|
||||
import Operation from "../Operation.mjs";
|
||||
import { PAYMENT_MAC_METHODS, verifyPaymentMac } from "../lib/PaymentMac.mjs";
|
||||
|
||||
/**
|
||||
* Verify payment MAC operation.
|
||||
*/
|
||||
class VerifyPaymentMAC extends Operation {
|
||||
|
||||
/**
|
||||
* VerifyPaymentMAC constructor.
|
||||
*/
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.name = "Verify payment MAC";
|
||||
this.module = "Payment";
|
||||
this.description = "Paste the message data into the input field and verify a payment-oriented MAC using one payment-facing operation.<br><br><b>Input:</b> message data in the selected input format.<br><b>Arguments:</b> choose the MAC method, provide either a direct key or a DUKPT BDK, add the KSN for DUKPT methods, and supply the expected MAC as hex.<br><br>This wrapper recomputes the MAC using the same payment-specific assumptions as the generate operation.";
|
||||
this.inlineHelp = "<strong>Input:</strong> message data.<br><strong>Args:</strong> choose the payment MAC method, provide the key context, then paste the expected MAC.";
|
||||
this.testDataSamples = [
|
||||
{
|
||||
name: "Static AES-CMAC verification sample",
|
||||
input: "1122334455667788",
|
||||
args: ["Hex", "AES-CMAC", "00112233445566778899AABBCCDDEEFF", "Hex", "", "339AF1AD1650E908", true]
|
||||
}
|
||||
];
|
||||
this.infoURL = "https://docs.aws.amazon.com/payment-cryptography/latest/DataAPIReference/API_VerifyMac.html";
|
||||
this.inputType = "string";
|
||||
this.outputType = "string";
|
||||
this.args = [
|
||||
{
|
||||
name: "Input format",
|
||||
type: "option",
|
||||
value: ["Hex", "UTF8", "Latin1", "Base64"],
|
||||
comment: "How to decode the input field before MAC verification."
|
||||
},
|
||||
{
|
||||
name: "MAC method",
|
||||
type: "option",
|
||||
value: PAYMENT_MAC_METHODS,
|
||||
comment: "Static-key HMAC and CMAC modes reuse the existing generic primitives. DUKPT modes derive a TDES session key first and then apply TDES-CMAC."
|
||||
},
|
||||
{
|
||||
name: "Key / BDK",
|
||||
type: "string",
|
||||
value: "",
|
||||
comment: "Provide the direct MAC key for HMAC or CMAC methods, or the clear BDK for DUKPT methods."
|
||||
},
|
||||
{
|
||||
name: "Key format",
|
||||
type: "option",
|
||||
value: ["Hex", "UTF8", "Latin1", "Base64"],
|
||||
comment: "How to decode the key input. Assumption: DUKPT BDK input must be <code>Hex</code>."
|
||||
},
|
||||
{
|
||||
name: "KSN (DUKPT only)",
|
||||
type: "string",
|
||||
value: "",
|
||||
comment: "Required only for DUKPT MAC methods. Provide the full 10-byte KSN as 20 hex characters."
|
||||
},
|
||||
{
|
||||
name: "Expected MAC (hex)",
|
||||
type: "string",
|
||||
value: "",
|
||||
comment: "MAC value to compare against, expressed as even-length hex."
|
||||
},
|
||||
{
|
||||
name: "Output as JSON",
|
||||
type: "boolean",
|
||||
value: true,
|
||||
comment: "When enabled, returns the recomputed MAC, comparison target, and validity result."
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {Object[]} args
|
||||
* @returns {string}
|
||||
*/
|
||||
run(input, args) {
|
||||
const [inputFormat, method, keyValue, keyFormat, ksn, expectedMac, outputJson] = args;
|
||||
const result = verifyPaymentMac(input, inputFormat, method, keyValue, keyFormat, ksn, expectedMac);
|
||||
return outputJson ? JSON.stringify(result, null, 4) : String(result.valid);
|
||||
}
|
||||
}
|
||||
|
||||
export default VerifyPaymentMAC;
|
||||
@ -221,6 +221,8 @@ input.toggle-string {
|
||||
filter: brightness(100%);
|
||||
}
|
||||
|
||||
.operation .form-group.is-filled label.bmd-label-floating,
|
||||
.operation .form-group.is-focused label.bmd-label-floating,
|
||||
.operation .bmd-form-group.is-filled label.bmd-label-floating,
|
||||
.operation .bmd-form-group.is-focused label.bmd-label-floating {
|
||||
top: 4px !important;
|
||||
|
||||
@ -255,6 +255,60 @@ TestRegister.addTests([
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Generate payment MAC: AES-CMAC",
|
||||
input: "1122334455667788",
|
||||
expectedOutput: "339AF1AD1650E908",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Generate payment MAC",
|
||||
args: ["Hex", "AES-CMAC", "00112233445566778899AABBCCDDEEFF", "Hex", "", 8, false]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Generate payment MAC: HMAC SHA-256",
|
||||
input: "1122334455667788",
|
||||
expectedOutput: "9300E1D36DD30415",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Generate payment MAC",
|
||||
args: ["Hex", "HMAC SHA-256", "00112233445566778899AABBCCDDEEFF", "Hex", "", 8, false]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Generate payment MAC: DUKPT MAC Request CMAC",
|
||||
input: "1122334455667788",
|
||||
expectedOutput: "3616961727FE155D",
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Generate payment MAC",
|
||||
args: ["Hex", "DUKPT MAC Request CMAC", "0123456789ABCDEFFEDCBA9876543210", "Hex", "FFFF9876543210E00008", 8, false]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Verify payment MAC: AES-CMAC",
|
||||
input: "1122334455667788",
|
||||
expectedOutput: JSON.stringify({
|
||||
method: "AES-CMAC",
|
||||
inputFormat: "Hex",
|
||||
inputHex: "1122334455667788",
|
||||
outputBytes: 8,
|
||||
fullMacHex: "339AF1AD1650E908A794284D91DC6D29",
|
||||
macHex: "339AF1AD1650E908",
|
||||
keySource: "Direct key input",
|
||||
expectedMacHex: "339AF1AD1650E908",
|
||||
valid: true
|
||||
}, null, 4),
|
||||
recipeConfig: [
|
||||
{
|
||||
op: "Verify payment MAC",
|
||||
args: ["Hex", "AES-CMAC", "00112233445566778899AABBCCDDEEFF", "Hex", "", "339AF1AD1650E908", true]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: "Derive ECDH key material: raw shared secret",
|
||||
input: ecdhPrivateKey,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user