import hmac import hashlib import struct from smartcard.CardConnection import CardConnection from smartcard.CardRequest import CardRequest from secret import SECRET def generate_payload(user_id: int) -> bytes: user_bytes = struct.pack(">H", user_id) mac = hmac.new( SECRET, user_bytes, hashlib.sha256 ).digest() mac_truncated = mac[:8] return user_bytes + mac_truncated def write_page(connection, page, data4): apdu = [0xFF, 0xD6, 0x00, page, 0x04] + data4 response, sw1, sw2 = connection.transmit(apdu) return sw1 == 0x90 and sw2 == 0x00 def write_ndef_text(connection, text, start_page=4) -> bool: text_bytes = text.encode("utf-8") lang = b"en" ndef_record = bytearray() ndef_record.append(0xD1) ndef_record.append(0x01) ndef_record.append(len(text_bytes) + 1 + len(lang)) ndef_record.append(0x54) ndef_record.append(len(lang)) ndef_record.extend(lang) ndef_record.extend(text_bytes) tlv = bytearray() tlv.append(0x03) tlv.append(len(ndef_record)) tlv.extend(ndef_record) tlv.append(0xFE) # Pad to multiple of 4 bytes while len(tlv) % 4 != 0: tlv.append(0x00) page = start_page for i in range(0, len(tlv), 4): chunk = list(tlv[i:i + 4]) if not write_page(connection, page, chunk): print(f"Konnte Seite {page} nicht schreiben. Ticket kaputt.") return False page += 1 print("Erfolgreich geschrieben") return True def write_secure_user_id(connection, user_id: int): payload = generate_payload(user_id) hex_string = payload.hex().upper() write_ndef_text(connection, hex_string) def main(): print("Auf Ticket warten...") card_request = CardRequest(timeout=None) card_service = card_request.waitforcard() connection = card_service.connection connection.connect(CardConnection.T1_protocol) try: user_id = int(input("User ID eingeben: ")) except ValueError: print("User ID muss numerisch sein!") exit(1) write_secure_user_id(connection, user_id) if __name__ == "__main__": main()