import nfc from nfc.clf import RemoteTarget import logging from time import time import os.path import coloredlogs coloredlogs.install() from base64 import b16encode, b16decode import sys import ndef import binascii from badge import Badge from os import system CONFIG_PAGES = { "NXP NTAG213": (0x29, 0x2A, 0x2B, 0x2C), "NXP NTAG215": (0x83, 0x84, 0x85, 0x86), "NXP NTAG216": (0xE3, 0xE4, 0xE5, 0xE6), } session_start = time() if __name__ == '__main__': log = logging.getLogger('nfc') nfc_type = sys.argv[1] balance = 0 if len(sys.argv) > 2: balance = sys.argv[2] elif nfc_type == 'coin': log.error("You cannot create empty coins.") exit() clf = nfc.ContactlessFrontend() log.info(f"Enrolling mode: {nfc_type}") log.info(f"Initial balance: {balance}") try: assert clf.open('tty:USB0:pn532') except TimeoutError: log.error('Got TimeoutError on reader connection attempt.') except AssertionError: log.error('There is no reader connected.') exit() # Set baud rate to 115200 to prevent reader from dying clf.device.chipset.set_serial_baudrate(115200) clf.device.chipset.transport.baudrate = 115200 try: while 1: target = clf.sense(RemoteTarget('106A'), iterations=10) if not target: continue start = time() tag = nfc.tag.activate(clf, target) if not tag: print("Tag was gone while writing.") break if tag.product not in ["NXP NTAG215"]: raise Exception(f"This tag ({tag.product}) is not compatible with the barcard system.") #print("\n".join(tag.dump())) #break badge = Badge(tag) password = badge.password() try: has_password = tag.read(CONFIG_PAGES[tag.product][0])[3] < 0xFF except: break if has_password: log.warning("TAG has a password already! Trying to re-enroll anyway.") tag.authenticate(password) #tx = Transaction(tag_id=tag.identifier) try: # Disable the mirror, for now page_addr = CONFIG_PAGES[tag.product][0] page = tag.read(page_addr)[:4] page[0] &= 0b111111 # Disable UID + COUNT mirror tag.write(page_addr, page) except: break # Activate it again tag = nfc.tag.activate(clf, target) if has_password: tag.authenticate(password) # Write the correct url depending on the type of wanted badge if nfc_type == 'badge': url = "https://go.foxo.me/fz23/bxxxxxxxxxxxxxxxxxxxxx" else: url = f"https://go.foxo.me/fz23/cxxxxxxxxxxxxxxxxxxxxx" tag.format() tag.ndef.records = [ndef.uri.UriRecord(url), ] if tag.ndef.records[0].uri != url: raise Exception("Written uri is different than expected.") boundary = tag.read(0x08) if not boundary.startswith(b"e/fz23/"): raise Exception(f"This tag does not seem to correctly store ndef data. Got wrong {boundary}") try: page_addr = CONFIG_PAGES[tag.product][0] page = tag.read(page_addr)[:4] page[0] |= 0b11 << 6 # Enable UID + COUNT mirror if tag.product == 'NXP NTAG215': page[2] = 0x0A # Location of UID + COUNT elif tag.product == 'NXP NTAG213': page[2] = 0x0B tag.write(page_addr, page) log.info("UID + COUNT mirror enabled.") except: raise break print('EC') badge.enable_count() tag = nfc.tag.activate(clf, target) if not has_password: print('PRT') badge.protect() with open(f'log_{int(session_start)}.txt', 'a') as f: f.write(f"{b16encode(tag.identifier).decode()},{nfc_type},{balance}\n") system('mpv success.wav') log.info(f"{time()-start:.2f} tag write done.") while clf.sense(RemoteTarget('106A')): pass system except KeyboardInterrupt: pass clf.close()