Add payment MAC wrapper operations

This commit is contained in:
J8k3 2026-04-25 09:20:28 -04:00
parent 7433b07f2b
commit 3f1b63378f
8 changed files with 471 additions and 30 deletions

View File

@ -25,8 +25,8 @@ Coverage legend:
| `EncryptData` | `Direct` / `Partial` | Direct for AES, TDES, RSA. Partial for DUKPT and EMV-derived encryption. | | `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. | | `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. | | `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. | | `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 by recomputing and comparing HMAC/CMAC. Partial for DUKPT MAC and EMV MAC 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. | | `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. | | `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. | | `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 ## 6) AWS `VerifyMac`: Recompute And Compare
Operations: Operations:
- `From Hex` - `Verify payment MAC`
- `HMAC` or `CMAC`
- `Take bytes`
Suggested use: Suggested use:
- Recompute the MAC using the same starter as `GenerateMac`. - Paste the message into the input field, choose the MAC method, and provide either the direct key or the DUKPT BDK plus KSN.
- Compare the result to the AWS `Mac` value manually or with a follow-on comparison recipe. - 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: Operations:
- `Generate card validation data` - `Generate card validation data`
@ -124,7 +138,7 @@ Notes:
- This directly covers software generation of CVV/CVV2/iCVV-style values. - This directly covers software generation of CVV/CVV2/iCVV-style values.
- Assumption: CVV2 forces service code `000` and iCVV forces `999`. - Assumption: CVV2 forces service code `000` and iCVV forces `999`.
## 8) AWS `VerifyCardValidationData`: CVV / CVV2 / iCVV ## 9) AWS `VerifyCardValidationData`: CVV / CVV2 / iCVV
Operations: Operations:
- `Verify card validation data` - `Verify card validation data`
@ -138,7 +152,7 @@ Notes:
## Partial Recipe Starters ## Partial Recipe Starters
## 9) AWS `EncryptData` / `DecryptData`: DUKPT-Derived Symmetric Flows ## 10) AWS `EncryptData` / `DecryptData`: DUKPT-Derived Symmetric Flows
Operations: Operations:
- `Derive DUKPT key` - `Derive DUKPT key`
- `AES Encrypt` or `AES Decrypt` or `Triple DES Encrypt` or `Triple DES Decrypt` - `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. - This is useful for offline vector work.
- It does not claim one-to-one parity with every AWS DUKPT encryption attribute combination. - 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 AWSs full DUKPT MAC union attributes.
## 11) AWS `VerifyAuthRequestCryptogram`: EMV ARQC Check ## 11) AWS `VerifyAuthRequestCryptogram`: EMV ARQC Check
Operations: Operations:
- `Generate EMV ARQC` - `Generate EMV ARQC`
@ -257,6 +257,7 @@ Why:
If you want closer AWS coverage, the highest-value missing operations are: 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. 1. PIN block encode/decode for ISO 9564 formats 0, 1, 3, and 4.
2. IBM 3624 and VISA PVV generation and verification. 2. IBM 3624 and VISA PVV generation and verification.
3. Dedicated EMV MAC and profile-specific EMV session-derivation helpers. 3. ISO 9797 and AS2805-specific MAC generation and verification.
4. Clear-to-encrypted and encrypted-to-encrypted PIN translation flows. 4. Dedicated EMV MAC and profile-specific EMV session-derivation helpers.
5. TR-31 unwrap and rewrap helpers for dynamic-key workflows. 5. Clear-to-encrypted and encrypted-to-encrypted PIN translation flows.
6. TR-31 unwrap and rewrap helpers for dynamic-key workflows.

View File

@ -62,7 +62,22 @@ Scope note:
- CVV2 forces service code `000` and iCVV forces `999`. - 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. - 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: Operations:
- `Generate EMV ARQC` - `Generate EMV ARQC`
@ -75,7 +90,7 @@ Scope note:
- This operation is intentionally limited to AES-CMAC-style EMV profiles. - 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. - 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: Operations:
- `Generate EMV ARPC` - `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. - 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. - Legacy 3DES EMV ARQC/ARPC flows are not covered.
## 10) Combined Message Triage ## 11) Combined Message Triage
Operations: Operations:
- `Parse TR-34 B9 envelope` - `Parse TR-34 B9 envelope`
- `Parse ASN.1 hex string` - `Parse ASN.1 hex string`

View File

@ -568,11 +568,21 @@
{ {
"name": "Payments", "name": "Payments",
"ops": [ "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-31 key block",
"Parse TR-34 B9 envelope", "Parse TR-34 B9 envelope",
"Calculate payment KCV", "Calculate payment KCV",
"Derive ECDH key material", "Derive ECDH key material",
"Derive DUKPT key", "Derive DUKPT key",
"Generate payment MAC",
"Verify payment MAC",
"Generate card validation data", "Generate card validation data",
"Verify card validation data", "Verify card validation data",
"Generate EMV ARQC", "Generate EMV ARQC",

175
src/core/lib/PaymentMac.mjs Normal file
View 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,
};

View 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;

View 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;

View File

@ -221,6 +221,8 @@ input.toggle-string {
filter: brightness(100%); 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-filled label.bmd-label-floating,
.operation .bmd-form-group.is-focused label.bmd-label-floating { .operation .bmd-form-group.is-focused label.bmd-label-floating {
top: 4px !important; top: 4px !important;

View File

@ -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", name: "Derive ECDH key material: raw shared secret",
input: ecdhPrivateKey, input: ecdhPrivateKey,