Skip to content

DiffieHellmanTr31KeyBlock import always fails with "KeyBlock data in the imported payload is invalid" - need KBPK derivation spec

1

I'm trying to import an external AES-256 KEK into AWS Payment Cryptography using DiffieHellmanTr31KeyBlock in ap-southeast-1. Every attempt returns:

ValidationException: KeyBlock data in the imported payload is invalid.

What I have verified working:

  • ECC_NIST_P521 key pair creation in AWS
  • RootCertificatePublicKey CA certificate import
  • TR-31 version D block construction (round-trip verified locally, MAC valid)
  • ECDH shared secret computation using AWS public key certificate

To diagnose, I exported a known AES-256 key from AWS via DiffieHellmanTr31KeyBlock and tried to decrypt it locally. All KBPK derivation variants fail MAC verification, including:

  • ConcatKDF SHA-256 with ASCII SharedInformation
  • ConcatKDF with empty otherinfo
  • ConcatKDF with hex-decoded SharedInformation
  • Raw shared secret SHA-256 hash
  • Truncated raw shared secret (first/last 32 bytes)
  • Various TR-31 subkey derivation methods (ENC/MAC labels, XOR, direct)

This suggests AWS uses an undocumented KBPK derivation from the ECDH shared secret.

Could someone share the correct Python implementation for:

  1. KBPK derivation from ECDH shared secret (exact ConcatKDF parameters and otherinfo format AWS expects)
  2. TR-31 version D subkey derivation (KBEK and KBMK from KBPK)
  3. TR-31 version D block construction

I've reviewed the AWS sample repo at aws-samples/ samples-for-payment-cryptography-service and the ECDH flow there delegates TR-31 wrapping to physical HSMs -- no software-side implementation is provided.

  • If my answer was helpful, I would appreciate it if you could mark it as the accepted answer.

1 Answer
2

The "KeyBlock data is invalid" error is almost never about the TR-31 structure itself, but rather a MAC mismatch caused by an incorrect KBPK (Key Block Protection Key) derivation. For AWS Payment Cryptography, the derivation must strictly follow NIST SP 800-56A and ANSI X9.143.

1. KBPK Derivation (ConcatKDF)

The most common point of failure is the construction of the OtherInfo (or SharedInfo) parameter in the ConcatKDF. AWS expects a specific binary structure:

  • Shared Secret (Z): Must be a fixed-length octet string. For NIST P-521, this must be exactly 66 bytes. If your library strips leading zeros, you must pad them back.
  • AlgorithmID: This is typically the OID or a defined bitstring for AES-256.
  • PartyU / PartyV Info: Ensure these contain the public keys or nonces in the correct order (usually Initiator followed by Responder).
  • SuppPubInfo: This must be the key length (e.g., 00 00 01 00 for 256 bits) represented as a 32-bit big-endian integer.

2. Subkey Derivation (KBEK and KBMK)

Once you have the KBPK, you must derive the encryption key (KBEK) and the MAC key (KBMK) using the NIST SP 800-108 Counter Mode KDF with AES-CMAC. The labels are critical:

  • KBEK: Label = 01 (Counter) || ENC (Label) || 00 (Separator) || 0100 (Context/Length).
  • KBMK: Label = 01 (Counter) || MAC (Label) || 00 (Separator) || 0100 (Context/Length).

3. TR-31 Block Construction (Version D)

For AES-based blocks (Optional Block ID 'D'), ensure the following:

  • Header Inclusion: The MAC calculation must include the 16-byte TR-31 header as "Associated Data."
  • Length Encoding: The length field in the header must include the header itself, the encrypted key, the optional blocks, and the 16-byte MAC.
  • Padding: If the payload is not a multiple of 16 bytes, use ISO/IEC 9797-1 Padding Method 2 (a 0x80 byte followed by zeros).

4. Implementation Checklist

  • Endianness: All integer values (lengths, counters) must be Big-Endian.
  • Key Attributes: The KeyUsage and KeyModesOfUse in your TR-31 header must match the KeyAttributes you defined in the AWS ImportKey request. A mismatch here will trigger a ValidationException even if the crypto is perfect.

Recommended Python Libraries

Instead of manual slicing, use the cryptography library's primitives:

  • cryptography.hazmat.primitives.kdf.concatkdf.ConcatKDFHash for the KBPK.
  • cryptography.hazmat.primitives.kdf.kbkdf.KBKDFCMAC for the KBEK/KBMK.

Note: If you are still seeing failures, verify the Key Usage codes. For example, a KEK should typically use usage K0 (Key Encryption Key) and mode E (Encrypt/Decrypt) or B (Wrap/Unwrap).

PS: I would try to use the cryptography.hazmat.primitives.kdf.kbkdf.KBKDFCMAC class in Python to ensure the NIST SP 800-108 implementation is standard-compliant.

EXPERT
answered 8 days ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.