Skip to content

Instantly share code, notes, and snippets.

@mistial-dev
Created December 17, 2023 02:43
Show Gist options
  • Save mistial-dev/f5881eee49a5c8b1ae7a23768b67d094 to your computer and use it in GitHub Desktop.
Save mistial-dev/f5881eee49a5c8b1ae7a23768b67d094 to your computer and use it in GitHub Desktop.
Diversify iClass Key (python)
import sys
from Cryptodome.Cipher import DES
'''
Cleaned up version of https://github.com/h3mag/hid-iclass/blob/master/hid-iclass.py for Python3, with the master key included.
Papers used:
(1) Heart of Darkness - exploring the uncharted backwaters of HID iCLASS security
(2) Dismantling iClass and iClass Elite
'''
'''
from Definition 10 in (2)
'''
PI = [0x0F,0x17,0x1B,0x1D,0x1E,0x27,0x2B,0x2D,0x2E,0x33,0x35,0x39,0x36,0x3A,0x3C,0x47,0x4B,0x4D,0x4E,0x53,0x55,0x56,0x59,0x5A,0x5C,0x63,0x65,0x66,0x69,0x6A,0x6C,0x71,0x72,0x74,0x78]
def ba2s(ba):
'''
helper method to convert a bytearray into a hexstring
'''
return bytearray(ba).hex()
def unpack(bytez):
'''
helper method to unpack a bytearray into x,y,z
x,y are 8bits each
z is an array of dim 8 with 6 bits per member
'''
v = int(bytez.hex(), 16)
x = 0
y = 0
z = [0]*8
for i in range(8):
z[i] = v&0x3f
v >>= 6
y = v&0xff
v >>= 8
x = v&0xff
return x,y,z
def ck(i,j,z):
if (i == 1) and (j == -1):
return z
if (j == -1):
return ck(i-1, i-2, z)
if z[i] == z[j]:
z[i] = j
return ck(i, j-1, z)
else:
return ck(i, j-1, z)
'''
from Definition 8 in (2)
'''
def check(zs):
zc1 = ck(3,2,zs[0:4])
zc2 = ck(3,2,zs[4:8])
zc = zc1+zc2
return zc
'''
from Definition 9 in (2)
'''
def permute(p,z,l,r):
rlp = len(p)
if rlp==0:
return []
lp = rlp-1
if p[lp]=="1":
return [(z[l]+1)&0x3f]+permute(p[:lp], z, (l+1)%8, r)
else:
return [z[r]]+permute(p[:lp], z, l, (r+1)%8)
'''
from Definition 11 in (2)
'''
def hash0(bytez):
x,y,z = unpack(bytez)
zs = [(z[i]%(63-i))+i for i in range(4)]
zs.extend([(z[i+4]%(64-i))+i for i in range(4)])
zc = check(zs)
p = PI[x%35]
if x&1:
p = (~p)&0xff
zt = permute("{:0>8b}".format(p), zc, 0, 4)
k = [0]*8
for i in range(8):
ybit = (y>>i)&1
pbit = (p>>i)&1
if ybit:
k[i]=((0x80|(((~zt[i])&0x3f)<<1)|(pbit&1))+1)&0xff
else:
k[i]=(zt[i]<<1)|((~pbit)&1)
return k
'''
from ch 2.5 in (2)
'''
def diversify_key(mkey, csn):
cipher = DES.new(mkey, DES.MODE_ECB)
crypt_csn = cipher.encrypt(csn)
div_key = hash0(crypt_csn)
return div_key
def print_usage():
print ("%s <CSN>" % (sys.argv[0]))
def main(hcsn):
MASTER_KEY = bytes.fromhex("aea684a6dab23278")
print("MASTER KEY:", ba2s(MASTER_KEY))
div_key = diversify_key(MASTER_KEY, bytes.fromhex(hcsn))
print("DIVERSIFIED DEBIT KEY (K1):", ba2s(div_key))
if __name__ == "__main__":
if len(sys.argv) == 2:
main(sys.argv[1])
else:
print_usage()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment