This is my code import hashlib import binascii from smartcard.System import readers from smartcard.util import toHexString from Crypto.Cipher import DES3 from Crypto.Random import get_random_bytes def compute_sha1(data): sha1 = hashlib.sha1() sha1.update(data.encode('ascii')) return sha1.digest() def adjust_parity(key): adjusted_key = bytearray(key) for i in range(len(adjusted_key)): byte = adjusted_key & 0xFE parity = 0 for bit in range(1, 8): parity ^= (byte >> bit) & 0x01 adjusted_key = byte | (parity ^ 0x01) return bytes(adjusted_key) def derive_keys(mrz_info): mrz_key_seed = mrz_info sha1_hash = compute_sha1(mrz_key_seed) k_enc = adjust_parity(sha1_hash[:8] + sha1_hash[8:16]) k_mac = adjust_parity(sha1_hash[8:16] + sha1_hash[:8]) return k_enc, k_mac def encrypt_3des_cbc(key, iv, data): cipher = DES3.new(key, DES3.MODE_CBC, iv) return cipher.encrypt(data) def compute_mac(k_mac, data): cipher = DES3.new(k_mac, DES3.MODE_CBC, iv=b'\x00' * 8) padded_data = data + b'\x80' + b'\x00' * (7 - (len(data) % 8)) mac = cipher.encrypt(padded_data)[-8:] return mac def compute_check_digit(data): weights = [7, 3, 1] total = 0 for i, char in enumerate(data): if char.isdigit(): value = int(char) elif char == '<': value = 0 else: value = ord(char) - 55 total += value * weights[i % 3] return str(total % 10) def main(): # this is the test codes but I'm actually using my real MRZ doc_number = "L898902C3" dob = "740812" doe = "120415" mrz_info = doc_number + compute_check_digit(doc_number) + dob + compute_check_digit(dob) + doe + compute_check_digit(doe) # Derive keys k_enc, k_mac = derive_keys(mrz_info) print(f"Kenc: {toHexString(list(k_enc))}") print(f"Kmac: {toHexString(list(k_mac))}") # Generate random numbers rnd_ifd = get_random_bytes(8) rnd_ic = get_random_bytes(8) k_ifd = get_random_bytes(8) print(f"rnd_ifd: {toHexString(list(rnd_ifd))}") print(f"rnd_ic: {toHexString(list(rnd_ic))}") print(f"k_ifd: {toHexString(list(k_ifd))}") # Construct S and encrypt it s = rnd_ifd + rnd_ic + k_ifd encrypted_s = encrypt_3des_cbc(k_enc, b'\x00' * 8, s) print(f"encryptedS: {toHexString(list(encrypted_s))}") # Compute MAC mac = compute_mac(k_mac, encrypted_s) print(f"MAC: {toHexString(list(mac))}") # Construct APDU apdu = b'\x00\x82\x00\x00\x20' + encrypted_s + mac print(f"APDU: {toHexString(list(apdu))}") # Select reader and connect to card r = readers() if len(r) == 0: print("Oops") return reader = r[0] connection = reader.createConnection() connection.connect() # Select MF select_mf = [0x00, 0xA4, 0x00, 0x00, 0x02, 0x3F, 0x00] response, sw1, sw2 = connection.transmit(select_mf) print(f"Select MF: {toHexString(list(response))} {sw1:02X} {sw2:02X}") # Select LDS select_lds = [0x00, 0xA4, 0x04, 0x0C, 0x07, 0xA0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01] response, sw1, sw2 = connection.transmit(select_lds) print(f"Select LDS: {toHexString(list(response))} {sw1:02X} {sw2:02X}") # Get Challenge get_challenge = [0x00, 0x84, 0x00, 0x00, 0x08] response, sw1, sw2 = connection.transmit(get_challenge) print(f"Get Challenge: {toHexString(list(response))} {sw1:02X} {sw2:02X}") # External Authenticate response, sw1, sw2 = connection.transmit(list(apdu)) print(f"External Authenticate: {toHexString(list(response))} {sw1:02X} {sw2:02X}") if __name__ == "__main__": main() Every attempt to work with the passport results in 67 00 response, using my ACR122 USB NFC reader. The idea is to get the NFC data (photo etc) from the passport. Why the code returns me invalid length? Continue reading...