RFID is a fun technology with a wide variety of applications. There are many different kinds of RFID: passive, active, semi-active, inductively coupled, e-field coupled, and others. In this article, I'll be covering some of the data formats of 125 KHz HID proximity cards. These cards are 125 kHz, inductively-coupled passive tags that use FSK modulation. It's important to note that they aren't compatible with 125 KHz EM4100 cards. Commonly used in the hobbyist world and some access control systems, EM4100 cards use ASK modulation and aren't compatible with HID proxmity systems.
HID Proximity cards are a very popular type of RFID used commonly used for access control. These cards or keyfobs usually must be presented in front of a reader to get into a building or parking garage.
These cards are typically be programmed to store only 26 to 40 bits, although some systems will use more or less. That's it. There is no intelligence in the card and no encryption. The data is read by a “dumb” reader, which then sends the bits to the access controller. The access controller will determine if the particular card is authorized.
There are several common formats used to decode the raw bits transmitted by the card. These bits can be broken down into 3 categories: facility code, card code, and parity bits. The “card code” is the code assigned to a particular card. It should be unique within the system, and is usually printed on the card itself. The “facility code” allows different buildings, regions or companies to have the same card codes but still have a different card overall. Parity bits are used for verifying the integrity of the data transmitted at the access control system.
Usually bits are sent to the access controller over Wiegand, but when they are sent over serial as hex data, some extra bits are added. A 1 bit is added before the rest of the bits so that you know exactly how many bits you have for format decoding (otherwise, if your first bit is a 0, you might decode improperly). Second, sometimes a checksum byte is added at the end, which is just the binary sum of all the other bits.
The 26 bit format is an industry standard open format. Any access controller should be able to understand it and anyone can buy cards with this format without restrictions. This is by far this is the most common format, and most systems that I've encountered use this format.
The 26 bits are broken down into an 8 bit facility code, a 16 bit card code, and two parity bits. The first bit is an even parity bit and covers the first 13 bits. Bits 2 to 9 are the facility code and bits 10-25 are the card code, stored big endian (MSB first). The last bit is an odd parity bit and covers the last 13 bits. There's only 255 possible facility codes and 65,535 possible card codes, so there's definitely duplicate cards out there.
The 35 bit HID Corporate 1000 format is a proprietary format used by HID. They control the sale of cards with this format to ensure there are no duplicates. This is the card format my school uses, and I had a difficult time figuring it out. I was able to determine the facility code and card code bit locations by just scanning a lot of my friends card and looking at the data. Since the card code is printed on the card, it wasn't too difficult. My school actually uses two site codes, one is reserved specifically for the research division. For a while, I just ignored the parity bits since I only cared about the facility code and card code. However, when I wanted to start emulating cards, I had to figure it out so that I could generate the correct bits. Extensive searching eventually led me to an old access controller manual that specified the format.
This format uses a 12 bit facility code (bits 3-14) and a 20 bit card code (bits 15-34). Bit 1 is an odd parity bit that covers all 35 bits. Bit 2 is an even parity covering bits 3,4,6,7,9,10,12,13,15,16,28,19,21,22,24,25,27,28,30,31,33,34. Bit 35 is odd parity, covering bits 2,3,5,6,8,9,11,12,14,15,17,18,20,21,23,24,26,27,29,30,32,33. When calculating the parity bits, you must calculate bit 2, bit 35, and finally bit 1. What a weird format. I'm guessing this parity scheme is supposed to add another layer of obscurity.
To decode the bit sequences from HID RFID readers using Wiegand, I usually connect the readers to a microcontroller and implement the decoding there. My Arduino Wiegand decoder demonstrates this for both the 26 bit and 35 bit formats.
Some HID readers can output RS-232 serial data instead of Weigand. The data is encoded as hexidecimal ASCII characters and usually includes a checksum. This card calculator I found online will decode some other formats, and you can look at the source to see how they decode the bits. Once you understand the card data format, it's easy to decode cards for your system.
You can also generate the hex or binary codes if you know the card code, facility code, and data format. The following python scripts will generate a hex code for a given card and facility code.
def bitCount(int_type): # return number 1's in a number when represented as binary count = 0 while(int_type): int_type &= int_type - 1 count += 1 return(count) def generate35bitHex(facilityCode, cardCode): # generates a hex code for HID 35 bit format card # see this page to understand formats: #http://www.pagemac.com/azure/data_formats.php cardData = (facilityCode << 21) + (cardCode << 1) # 2nd MSB even parity parity1 = bitCount(cardData & 0x1B6DB6DB6) & 1 cardData += (parity1 << 33) # add the parity bit (we need it for further parity calculations) # MSB odd parity is the LSB parity2 = bitCount(cardData & 0x36DB6DB6C) & 1 ^ 1 cardData += parity2 # add the parity bit # LSB odd parity (covers all 34 other bits) parity3 = bitCount(cardData) & 1 ^ 1 cardData += (parity3 << 34) # add the parity bit return "%09X" % cardData # convert to hex, pad with zeros (9 characters) def generate26bitHex(facilityCode, cardCode): # generates a hex code for HID 26 bit format card # see this page to understand formats: #http://www.pagemac.com/azure/data_formats.php cardData = (facilityCode << 17) + (cardCode << 1) # MSB even parity (covers 12 MSB) parity1 = bitCount(cardData & 0x1FFE000) & 1 # LSB odd parity (covers 12 LSB) parity2 = bitCount(cardData & 0x0001FFE) & 1 ^ 1 cardData += (parity1 << 25) + (parity2) return "%06X" % cardData # convert to hex, pad with zeros (6 characters) facilityCode = 54 cardCode = 360100 generate35bitHex(facilityCode, cardCode)
Writeup: March 2009