86 lines
2.1 KiB
Python
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() |