Seite 1 von 1

RFID-UID mit 4 oder 7 Bytes?

Verfasst: Di 14. Jun 2022, 13:02
von Heinrichs
Die Firma Mifare bietet ihre Mifare classic card 1K in zwei verschiedenen Varianten an:
  • 7-Byte UID (MF1S500yXDyy)
  • 4-Byte NUID (MF1S503yXDyy)
Bei der 4-Byte-Variante ist die ID-Nummer "not unique"; sie ist also nicht einzigartig. Da es nur 256*256*256*256 = 4.294.967.296 ID-Nummern mit 4 Bytes geben kann, ist dies nicht erstaunlich; denn die Anzahl der produzierten Karten ist deutlich höher. Dies gilt um so mehr, als es eine große Anzahl von Clonen gibt.

Bei der 7-Byte-Variante gibt es immerhin ca. 72 Billiarden (72.000.000.000.000.000) verschiedene IDs. Diese Variante kostet etwas mehr als die 4-Byte-Variante. Die (preiswerten) Clone dürften meist mit einer 4-Byte-NUID versehen sein.

Wie können Sie nun herausfinden, ob Ihre Karte eine 4-Byte-NUID besitzt oder eine 7-Byte-UID. Nun, die einzelnen Bytes der ID findet man in Block 0 der Karte, und zwar bilden sie die ersten 4 bzw. 7 Bytes. Bei der 4-Byte-Variante steht im 5. Byte der BBC-Wert. Dabei handelt es sich um einen Kontrollwert, welcher aus der XOR-Verknüpfung der ersten 4 Bytes besteht:

BBC = Byte0 ^ Byte1 ^ Byte2 ^ Byte3

Mit dem folgenden Programm mfrc_read_uid_bbc_display_1.py können Sie diesen Wert ausrechnen und anzeigen lassen; stimmt er mit dem Byte4 von Block 0 überein, ist es sehr wahrscheinlich, dass Ihre Karte eine 4-Byte-Variante ist.

Code: Alles auswählen

# read_uid_bbc_display_1.py
# liest UID (inkl. BBC) des Tags (RFID-Karte/Chip) und gibt sie zusammen mit der berechneten BBC auf dem Display und dem Terminal aus

# Quelle: https://github.com/Tasm-Devil/micropython-mfrc522-esp32; ergänzt und modifiziert für TTGO-T-Display

# Achtung: Vor dem Start des Programms muss das Modul mfrc522.py auf den ESP32 hochgeladen werden.

# Initialisierungen...

from machine import Pin, SPI, SoftSPI
import st7789
import vga2_16x16 as font1 # mit Umlauten
import vga2_8x16 as font2
from os import uname
release = uname().release[0:4]
id = 2 # z. B. für V 1.12 und V 1.14
if release == '1.18':
    id = 1    
spi = SPI(id, baudrate=20000000, polarity=1, sck=Pin(18), mosi=Pin(19)) # 1. Parameter = 1 für Firmware v1.18
display = st7789.ST7789(spi, 135, 240,  reset=Pin(23, Pin.OUT), cs=Pin(5, Pin.OUT), dc=Pin(16, Pin.OUT), backlight=Pin(4, Pin.OUT), rotation=3)
display.init()

from time import sleep_ms

from mfrc522 import MFRC522
# nach: https://github.com/Tasm-Devil/micropython-mfrc522-esp32

sck = Pin(17, Pin.OUT)
mosi = Pin(15, Pin.OUT)
miso = Pin(12, Pin.OUT)
softspi = SoftSPI(baudrate=100000, polarity=0, phase=0, sck=sck, mosi=mosi, miso=miso)
sda = Pin(25, Pin.OUT) # (SDA = ChipSelect)

# Funktionen...

def umlaute_ersetzen(zk):
    zk = zk.replace(b'Ä', b'\x8e')  
    zk = zk.replace(b'ä', b'\x84')
    zk = zk.replace(b'Ö', b'\x99')
    zk = zk.replace(b'ö', b'\x94')
    zk = zk.replace(b'Ü', b'\x9a')
    zk = zk.replace(b'ü', b'\x81')
    zk = zk.replace(b'ß', b'\xe1')
    return zk

def do_bbc(uid_list):
    bbc = uid_list[0] ^ uid_list[1] ^ uid_list[2] ^ uid_list[3] # XOR...
    return bbc
    

def do_read_uid():
    try:
        while True:
            rdr = MFRC522(softspi, sda)
            uid = ""
            (stat, tag_type) = rdr.request(rdr.REQIDL) # liefert stat (stat = 2 -> Err; stat = 0 -> OK)
            if stat == rdr.OK: # Karte/Chip vorhanden
                (stat, raw_uid) = rdr.anticoll() # raw_uid besteht aus 4 Bytes für die (N)UID UND dem BBC
                # rdr.anticoll() kontrolliert, ob nur ein einziges RFID-Objekt detektiert wird (d. h. keine Collision vorliegt);
                # in diesem Fall erhält stat den Wert rdr.OK und raw_uid eine Liste mit 4 Bytes
                
                # UID lesen und anzeigen:
                if stat == rdr.OK: 
                    uid = ('0x%02x%02x%02x%02x' % (raw_uid[0], raw_uid[1], raw_uid[2], raw_uid[3])) # setzt 4 Bytes zu einem "HEX-String" zusammen
                    # print('uid mit BBC: ', raw_uid) # Dezimal (inkl. BBC)
                    print('uid (mit BBC): ', [hex(n) for n in raw_uid]) # Hexadezimal
                    bbc = do_bbc(raw_uid[:4])
                    # print('BBC: ', bbc)
                    print('BBC (berechnet): ' + ('0x%02x' % bbc))
                    print()
                    display.text(font1, uid, 10, 40)
                    display.text(font1, 'BBC: ' + ('0x%02x' % bbc), 10, 60)
                    sleep_ms(100)
            else:
                print('Karte!')
                display.text(font1, 'Karte!        ', 10, 40)
                display.text(font1, '              ', 10, 60)

    except KeyboardInterrupt: # mit Str-C
        print()
        print('Tschüss')
        display.text(font1, umlaute_ersetzen(b'Tschüss!   '), 10, 100)


# Hauptprogramm:

display.fill(0)
display.text(font1, 'RFID-RC522', 10, 10)
display.text(font1, 'Karte!', 10, 40)
display.text(font2, 'Exit mit Strg-C', 10, 100)
do_read_uid()
Wem das benutzte Display des TTGO nicht zur Verfügung steht, kann die entsprechenden Display-Befehle auskommentieren oder löschen.

.