How to use pyscard to read NFC tag UID
Updated December 16, 2024 17:21
Overview
If you have NFC tags in your possession, you may want to read the data on the tag. One of the easiest ways to do this is using an SDK specifically created for connecting to and reading data from a tag.
In this tutorial, we'll go over the requirements necessary to connect a reader to your computer, send APDUs to your reader, and collect a tag's UID.
We'll be using an ACS WalletMate for our purposes, but the guide should work for other readers that are compliant with the CCID protocol.
Installing pcsc-lite
First we'll need the drivers that allow our computer to properly interface with the reader. For anyone using an ACS WalletMate, you'll need to download the drivers for your specific OS from the ACS website.
Once you download them, be sure to install them! If you do not install them, then your script will not work. This will require you to restart your computer if you're using a Mac.
For anyone else, you'll likely need pcsc-lite which is a library for connecting to smart cards with your personal computer. It can be installed with brew:
brew install pcsc-lite
Installing pyscard and other dependencies
While pyscard is not the only NFC SDK, it is the one we like the best. For this tutorial you'll need the pyscard python package. You only need to run one of these:
python3 -m pip install pyscard
pip3 install pyscard
Connecting to the reader
So now that we have the drivers, and the SDK installed. Let's plug our reader into the computer we want to run scripts on. Please note that you could very easily plug the reader into a Raspberry Pi. For our purposes, we're going to be using a Macbook Air.
Sending APDUs
The whole purpose of pyscard is to make sending APDUs easier. We have a useful crash course on APDUs here if you are unfamiliar with them. We're going to need to send an APDU to our WalletMate, so let's do it.
Reading NFC tag UID
The APDU for getting an NFC tags UID on an ACS WalletMate is the following:
CLA | INS | P1 | P2 | LE |
FF | CA | 00 | 00 | 00 |
We can do that in python with pyscard like so:
Make sure you have your tag touching the reader when you run this script!
from smartcard.scard import (
SCardGetErrorMessage,
SCARD_SCOPE_USER,
SCARD_S_SUCCESS,
SCARD_SHARE_SHARED,
SCARD_PROTOCOL_T0,
SCARD_PROTOCOL_T1,
SCARD_CTL_CODE,
SCardEstablishContext,
SCardListReaders,
SCardConnect,
SCardControl
)
hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
assert hresult == SCARD_S_SUCCESS
hresult, readers = SCardListReaders(hcontext, [])
assert len(readers) > 0
reader = readers[0]
hresult, hcard, dwActiveProtocol = SCardConnect(hcontext, reader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1)
apdu_cmd = [0xFF, 0xCA, 0x00, 0x00, 0x00]
hresult, response = SCardControl(hcard, SCARD_CTL_CODE(3500), apdu_cmd)
if hresult != SCARD_S_SUCCESS:
print(SCardGetErrorMessage(hresult))
print('NFC tag UID is:', ''.join(map(lambda x: f'{x:02x}', response[:-2])).replace('0x', ''))
When you have a card placed against the reader scan surface and you run this, you should see:
Conclusion
We went over some important tools for being able to collect a tag's UID in this guide, including pcsc-lite, the pyscard SDK and APDUs. You should now feel more confident in your ability to connect to a reader and get NFC tag UIDs!
If you have any feedback on this article, let us know! Email content@passninja.com