[Python] Trying to perform authentication over my NFC chip for passport/ID in Python

Discussão em 'Python' iniciado por Stack, Maio 17, 2025.

  1. Stack

    Stack Membro Participativo

    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...

Compartilhe esta Página