from Crypto.Cipher import AES
def gen_subkeys(K,cipher):
"""Generate subkeys of cipher"""
from struct import pack, unpack
L = cipher.encrypt("00000000000000000000000000000000".decode("hex"))
LHigh = unpack(">Q",L[:8])[0]
LLow = unpack(">Q",L[8:])[0]
K1High = ((LHigh << 1) | ( LLow >> 63 )) & 0xFFFFFFFFFFFFFFFF
K1Low = (LLow << 1) & 0xFFFFFFFFFFFFFFFF
if (LHigh >> 63):
K1Low ^= 0x87
K2High = ((K1High << 1) | (K1Low >> 63)) & 0xFFFFFFFFFFFFFFFF
K2Low = ((K1Low << 1)) & 0xFFFFFFFFFFFFFFFF
if (K1High >> 63):
K2Low ^= 0x87
K1 = pack(">QQ", K1High, K1Low)
K2 = pack(">QQ", K2High, K2Low)
return K1, K2
def xor(data, key):
"""XOR function"""
from itertools import izip, cycle
xored = "".join(chr(ord(x) ^ ord(y)) for (x,y) in izip(data, cycle(key)))
return xored.encode("hex")
def cmac_div(key, UID, Sector_number):
""""""
from Crypto.Cipher import AES
IV = "00000000000000000000000000000000".decode( "hex" ) ##Init vector for AES
cipher = AES.new(key.decode( "hex" ), AES.MODE_CBC, IV) ##AES in Cipher block Chaining mode, Init Vector=00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
K1, K2 = gen_subkeys( key, cipher )
xorkey = K1
M = "01" + UID + Sector_number
padding = "8000000000000000000000000000000000000000000000000000"
if len(M) < 64: ## if padding needed
M += padding
xorkey = K2
if len(M) != 64:
print "M != 32 byte!"
exit()
xordata = M[-32:].decode("hex")##last 16 bytes of M
xoreddata = xor(xordata,xorkey)##xor xordata with K1 of K2
M = M[:-32] + xoreddata ##replace last 16 bytes with xordata
cipher = AES.new( key.decode("hex"), AES.MODE_CBC, IV)##reset cipher
divkey = cipher.encrypt( M.decode( "hex" ) ).encode( "hex" )[-32:-20] ##AES M and slice out the right piece
print "AES version"
print "Masterkey:\t " + key.upper()
print "UID:\t\t " + UID.upper()
print "Sector:\t\t " + Sector_number.upper()
print "Subkey 1:\t " + K1.encode("hex").upper()
print "Subkey 2:\t " + K2.encode("hex").upper()
print "Message:\t " + M.upper()
print "Diversified key: " + divkey.upper()
print
return divkey
def des3_div(key, UID, Sector_number, MIFkey):
""""""
from Crypto.Cipher import DES3
trailerblock = 4*int(Sector_number)+3 ##van sector naar trailerblock van sector
trailerblock = "{:02x}".format(trailerblock)
M = MIFkey[:8]
M += xor( MIFkey[8:10].decode( "hex" ),UID[:2].decode( "hex" ))
M += xor( MIFkey[10:].decode( "hex" ),UID[2:4].decode( "hex" ) )
M += xor( trailerblock.decode( "hex" ), UID[4:6].decode( "hex" ) )
M += UID[6:]
cipher = DES3.new( key.decode( "hex" ) )
divkey=cipher.encrypt( M.decode( "hex" ) ).encode( "hex" )[2:14]
print "3DES version"
print "Masterkey:\t " + key.upper()
print "UID:\t\t " + UID.upper()
print "Sector:\t\t " + Sector_number.upper()
print "Trailer Block:\t " + trailerblock
print "Mifare key:\t " + MIFkey.upper()
print "Message:\t " + M.upper()
print "Diversified key: " + divkey.upper()
print
return divkey
if __name__ == "__main__":
masterkey = "00112233445566778899aabbccddeeff"
UID="000000"
Sector_number="07"
MIFkey="A0A1A2A3A4A5" ## Only needed for 3DES version(MF RC171)
cmac_div(masterkey, UID, Sector_number)
des3_div(masterkey, UID, "01", MIFkey)
# your code goes here