• Source
    1. from Crypto.Cipher import AES
    2. def gen_subkeys(K,cipher):
    3. """Generate subkeys of cipher"""
    4. from struct import pack, unpack
    5.  
    6. L = cipher.encrypt("00000000000000000000000000000000".decode("hex"))
    7.  
    8. LHigh = unpack(">Q",L[:8])[0]
    9. LLow = unpack(">Q",L[8:])[0]
    10.  
    11. K1High = ((LHigh << 1) | ( LLow >> 63 )) & 0xFFFFFFFFFFFFFFFF
    12. K1Low = (LLow << 1) & 0xFFFFFFFFFFFFFFFF
    13.  
    14. if (LHigh >> 63):
    15. K1Low ^= 0x87
    16.  
    17. K2High = ((K1High << 1) | (K1Low >> 63)) & 0xFFFFFFFFFFFFFFFF
    18. K2Low = ((K1Low << 1)) & 0xFFFFFFFFFFFFFFFF
    19.  
    20. if (K1High >> 63):
    21. K2Low ^= 0x87
    22.  
    23. K1 = pack(">QQ", K1High, K1Low)
    24. K2 = pack(">QQ", K2High, K2Low)
    25.  
    26. return K1, K2
    27.  
    28. def xor(data, key):
    29. """XOR function"""
    30. from itertools import izip, cycle
    31. xored = "".join(chr(ord(x) ^ ord(y)) for (x,y) in izip(data, cycle(key)))
    32. return xored.encode("hex")
    33.  
    34. def cmac_div(key, UID, Sector_number):
    35. """"""
    36. from Crypto.Cipher import AES
    37.  
    38. IV = "00000000000000000000000000000000".decode( "hex" ) ##Init vector for AES
    39. 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
    40. K1, K2 = gen_subkeys( key, cipher )
    41. xorkey = K1
    42.  
    43. M = "01" + UID + Sector_number
    44. padding = "8000000000000000000000000000000000000000000000000000"
    45.  
    46. if len(M) < 64: ## if padding needed
    47. M += padding
    48. xorkey = K2
    49.  
    50. if len(M) != 64:
    51. print "M != 32 byte!"
    52. exit()
    53.  
    54. xordata = M[-32:].decode("hex")##last 16 bytes of M
    55. xoreddata = xor(xordata,xorkey)##xor xordata with K1 of K2
    56. M = M[:-32] + xoreddata ##replace last 16 bytes with xordata
    57.  
    58. cipher = AES.new( key.decode("hex"), AES.MODE_CBC, IV)##reset cipher
    59. divkey = cipher.encrypt( M.decode( "hex" ) ).encode( "hex" )[-32:-20] ##AES M and slice out the right piece
    60.  
    61. print "AES version"
    62. print "Masterkey:\t " + key.upper()
    63. print "UID:\t\t " + UID.upper()
    64. print "Sector:\t\t " + Sector_number.upper()
    65. print "Subkey 1:\t " + K1.encode("hex").upper()
    66. print "Subkey 2:\t " + K2.encode("hex").upper()
    67. print "Message:\t " + M.upper()
    68. print "Diversified key: " + divkey.upper()
    69. print
    70.  
    71. return divkey
    72.  
    73. def des3_div(key, UID, Sector_number, MIFkey):
    74. """"""
    75. from Crypto.Cipher import DES3
    76.  
    77. trailerblock = 4*int(Sector_number)+3 ##van sector naar trailerblock van sector
    78. trailerblock = "{:02x}".format(trailerblock)
    79.  
    80. M = MIFkey[:8]
    81. M += xor( MIFkey[8:10].decode( "hex" ),UID[:2].decode( "hex" ))
    82. M += xor( MIFkey[10:].decode( "hex" ),UID[2:4].decode( "hex" ) )
    83. M += xor( trailerblock.decode( "hex" ), UID[4:6].decode( "hex" ) )
    84. M += UID[6:]
    85.  
    86. cipher = DES3.new( key.decode( "hex" ) )
    87. divkey=cipher.encrypt( M.decode( "hex" ) ).encode( "hex" )[2:14]
    88.  
    89. print "3DES version"
    90. print "Masterkey:\t " + key.upper()
    91. print "UID:\t\t " + UID.upper()
    92. print "Sector:\t\t " + Sector_number.upper()
    93. print "Trailer Block:\t " + trailerblock
    94. print "Mifare key:\t " + MIFkey.upper()
    95. print "Message:\t " + M.upper()
    96. print "Diversified key: " + divkey.upper()
    97. print
    98.  
    99. return divkey
    100.  
    101. if __name__ == "__main__":
    102.  
    103. masterkey = "00112233445566778899aabbccddeeff"
    104. UID="00000000"
    105. Sector_number="00"
    106. MIFkey="A0A1A2A3A4A5" ## Only needed for 3DES version(MF RC171)
    107.  
    108. cmac_div(masterkey, UID, Sector_number)
    109. des3_div(masterkey, UID, "01", MIFkey)
    110. # your code goes here