Skip to content

Instantly share code, notes, and snippets.

Created December 31, 2019 12:54
Show Gist options
  • Save ceres-c/cbf437f9af9e946c96550fd7e1e77cef to your computer and use it in GitHub Desktop.
Save ceres-c/cbf437f9af9e946c96550fd7e1e77cef to your computer and use it in GitHub Desktop.
CR95HF Python script to read NXP ICODE tags in privacy mode
# Author: ceres-c 2019-12-29
# Authenticate to ICODE SLI tags
import hid
# Global defines & commands
password = [0x00, 0x00, 0x00, 0x00] # You have to find it yourself, try to search online in german ;-)
cmd_get_random = [0x02, 0xB2, 0x04]
cmd_set_pswd = [0x02, 0xB3, 0x04, 0x04] # The password must be appended
cmd_read_data = [0x02, 0x20] # The sector you want to read must be appended
Allows to configure ISO15693 reader parameters
h (hid device object)
append_crc (bool): If True ISO15 CRC is added after the data APDU.
dual_subcarrier (bool): If True data is sent in dual subcarrier mode, else single sub
modulation_10 (bool): If True 10% modulation, else 100% mod
wait_for_SOF (bool): If True the reader will wait for tag's SOF, else it'll respects ISO's standard 312-μs delay
speed (int): Can assume the following values
0: 26 Kbps (H)
1: 52 Kbps
2: 6 Kbps (L)
3: RFU
def CR95HF_ISO15_configure(h, append_crc=True, dual_subcarrier=False, modulation_10=False, wait_for_SOF=False, speed=0):
payload = []
payload.append(0x01) # HID related, not relevant
payload.append(0x02) # CR95HF ProtocolSelect command
payload.append(0x02) # Length of following data
payload.append(0x01) # ISO15693 protocol selection
parameters = 0
parameters |= (append_crc << 0)
parameters |= (dual_subcarrier << 1)
parameters |= (modulation_10 << 2)
parameters |= (wait_for_SOF << 3)
parameters |= (speed << 4)
h.write(payload) # This is used only to empty the buffer
Allows to send and receive data from an NFC ISO15693 tag
h (hid device object)
data (byte list)
(int, byte list) A tuple with the error code and the data from the tag.
Successful read has a 0x80 error code
Other errors can be found in the CR95HF datasheet
def CR95HF_ISO15_send_recv(h, data):
payload = []
payload.append(0x01) # HID related, not relevant
payload.append(0x04) # SendRecv command
d =
ret_code = d[1]
ret_data = d[3:d[2]+2] # Data length is in response byte 2
return (ret_code, ret_data)
# connect to reader
h = hid.device(), 0xd0d0)
CR95HF_ISO15_configure(h, wait_for_SOF=True)
ret_code, random = CR95HF_ISO15_send_recv(h, cmd_get_random)
if ret_code != 0x80:
print("Error code 0x{:02X} reading random from the tag!".format(ret_code))
password_xor = []
password_xor.append(password[0] ^ random[1])
password_xor.append(password[1] ^ random[2])
password_xor.append(password[2] ^ random[1])
password_xor.append(password[3] ^ random[2])
print ("Auth command paylod:", [hex(i) for i in cmd_set_pswd])
ret_code, auth_res = CR95HF_ISO15_send_recv(h, cmd_set_pswd)
if ret_code != 0x80:
print("Error code 0x{:02X} authenticating to the tag!".format(ret_code))
print("Successfully authenticated to the tag")
for i in range(0, 8):
cmd_read_data_updated = cmd_read_data + [i]
ret_code, read_data = CR95HF_ISO15_send_recv(h, cmd_read_data_updated)
print("Block:", i, "data:", [hex(i) for i in read_data])
Copy link

Great work @ceres-c! Can you recommend a specific RFID reader using the CR95HF chipset?

Copy link

ceres-c commented Jun 5, 2020

@Erechtheus I was using the ST M24LR kit, one of the many Discovery boards. It can be bought for cheap on eBay :-)

Copy link

Thanks, I'll give it a shot :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment