NFC_Client/nfc_reader.py

92 lines
2.3 KiB
Python

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