I am trying to implement TR-31 decryption into my test application. Because I don't have TR31 standard from ANSI i relay on free materials :)
I am able to get the clear key using Cryptographics Calculator.
KBPK: 33333333333333334444444444444444
TR-31 Key block: B0080P0TD00S00003A74E0769701C712CC87ECB93E9455CC2BF16C71B30F507E524F535F42B56027
----------------------------------------
TR-31 Header: B0080P0TD00S0000
----------------------------------------
Version Id: B
Block Length: 0080
Key Usage: P0
Algorithm: T
Mode of Use: D
Key Version No.: 00
Exportability: S
Num. of Opt. blocks: 00
Reserved: 00
Optional Blocks:
TR-31 Encrypted key: 3A74E0769701C712CC87ECB93E9455CC2BF16C71B30F507E
TR-31 MAC: 524F535F42B56027
----------------------------------------
Plain Key: 94892FF715E992BC4AC4E56116582AE6
But if I try to do intermediate steps myself I don get the same result.
From the available online sources I have found out that for B version KBEK is made of two components 3DES CMAC of hex "0100000000000080" and "0200000000000080". After result of CMAC is joined we should have KBEK.
Finally we get clear key by using 3DES decryption in CBC mode. KB MAC is used as IV.
Unfortunately following these steps didn't get me to clear key. Any help would be appreciated.
I cannot reproduce the problem. Here is a Python code that generates a TR-31 key block. From this you can derive the algorithm for decryption, which is the same as the one you described:
The two partial keys and the total key are:
KBEK_1: cee717dc1d467889
KBEK_2: 92c99160462c9def
KBEK : cee717dc1d46788992c99160462c9def
KBEK_1
results when the CMAC/3DES is created for 0x0100000000000080 using the KBPK. Similarly, KBEK_2
results if the CMAC/3DES is created for 0x0200000000000080 using the KBPK. The KBEK is obtained by concatenating both partial keys.
The plaintext key block and the plaintext key are:
Plaintext key block: 008094892ff715e992bc4ac4e56116582ae61a0e90859c76
Plaintext key: 94892ff715e992bc4ac4e56116582ae6
The plaintext key block is obtained by decrypting the encrypted key using 3DES/CBC with the KBEK. The MAC is applied as IV. The first two bytes 0x0080 indicate the length of the key, so that the plaintext key can be determined from this, which corresponds to the expected value.
Below you will find a Python code that determines the key using the PyCryptodome library:
from Crypto.Hash import CMAC
from Crypto.Cipher import DES3
def generateKey(KBPK):
KBEK_1 = generateCMAC(bytes.fromhex("0100000000000080"), KBPK)
KBEK_2 = generateCMAC(bytes.fromhex("0200000000000080"), KBPK)
KBEK = KBEK_1 + KBEK_2
print("KBEK_1: " + KBEK_1.hex()) # KBEK_1: cee717dc1d467889
print("KBEK_2: " + KBEK_2.hex()) # KBEK_2: 92c99160462c9def
print("KBEK : " + KBEK.hex()) # KBEK : cee717dc1d46788992c99160462c9def
return KBEK
def generateCMAC(data, key):
cmac = CMAC.new(key, ciphermod=DES3)
cmac.update(data)
return cmac.digest()
KBPK = bytes.fromhex('33333333333333334444444444444444')
iv = bytes.fromhex('524F535F42B56027') # iv = MAC
encKey = bytes.fromhex('3A74E0769701C712CC87ECB93E9455CC2BF16C71B30F507E')
KBEK = generateKey(KBPK)
cipher = DES3.new(KBEK, DES3.MODE_CBC, iv)
ptKB = cipher.decrypt(encKey) # plaintext key block
lenKey = int.from_bytes(ptKB[:2], "big") // 8
key = ptKB[2:2+lenKey]
print("Plaintext key block: " + ptKB.hex()) # Plaintext key block: 008094892ff715e992bc4ac4e56116582ae61a0e90859c76
print("Plaintext key: " + key.hex()) # Plaintext key: 94892ff715e992bc4ac4e56116582ae6