EZGG-LAN-NFC-Tools/card_writer.py
David Rodenkirchen ddc60f80fb initial commit
2026-02-26 08:18:45 +01:00

86 lines
2.1 KiB
Python

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()