import nfc from nfc.clf import RemoteTarget import httpx import logging import binascii from base64 import b16encode from os.path import join from config import * from time import sleep from hashlib import sha3_512 import coloredlogs coloredlogs.install() def password(tag): x = tag.identifier for i in range(ITERATIONS): x = sha3_512(x + SALT).digest() return x[:6] CONFIG_PAGES = { "NXP NTAG213": (0x29, 0x2A, 0x2B, 0x2C), "NXP NTAG215": (0x83, 0x84, 0x85, 0x86), "NXP NTAG216": (0xE3, 0xE4, 0xE5, 0xE6), } if __name__ == '__main__': log = logging.getLogger('nfc') clf = nfc.ContactlessFrontend() 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, delay=0.1) if not target: continue count = None tag_id = target.sdd_res is_secure = False if not BOOPBOX_ID: try: tag = nfc.tag.activate(clf, target) except: log.error(f"TAG {tag_id} is gone.") continue try: if SECURE and tag.product == "NXP NTAG215": has_password = tag.read(CONFIG_PAGES[tag.product][0])[3] < 0xFF if has_password: psw = password(tag) if tag.authenticate(psw): is_secure = True except: log.error("Couldn't verify tag.") # Try to get the read count as well. try: if tag.product == "NXP NTAG215": count = tag.transceive(binascii.unhexlify('3902'), timeout=0.05) # READ_CNT command count = int.from_bytes(count, byteorder='little') except nfc.tag.tt2.Type2TagCommandError: log.error("Tag count is enabled, couldn't get a response") except AttributeError: log.error("Lost connection to tag...") try: res = httpx.post(SERVER, json={'id': b16encode(tag_id).decode(), 'is_secure': is_secure, 'count': count, 'boopbox_id': BOOPBOX_ID}) except Exception as e: log.error(e) else: log.info(f"Booped {b16encode(tag_id).decode()} (secure = {is_secure}) (count = {count})") while clf.sense(RemoteTarget('106A')): sleep(0.1) except KeyboardInterrupt: clf.close()