rfidiot qr code

News

October 2012: Migrated source code to https://github.com/AdamLaurie/RFIDIOt. I realised one of the reasons I haven't been doing many updates is because it's always such a faff getting a new tarball together, updating the webpage etc., etc. Now, should you be vaguely interested, you can simply watch the project on github and get notified whenever a change is committed... Even better, if you have updates you want to contribute, just fork and create a merge request... (The first of which was Nick von Dadelszen's Android support package). Sweet!

I will follow my usual practice of 'commit early, commit often', so whenever I'm working on something, expect daily updates... Speaking of which, I finally got around to bringing libNFC support up to date, so it now works with libnfc 1.6.0-rc1.

September 2011: Added Throwing Star LAN Tap to shop. Another cool Michael Ossmann project!

March 2011: Added ubertooth-one to shop. This is an open source 2.4 GHz wireless development platform suitable for Bluetooth experimentation, designed by Michael Ossmann. This is very cool... It brings hardware that is normally in the realms of thousands of pounds down to under 100! Sweet! You can build it yourself from the plans on his site, or order it ready built. Update - 13th June 2011 - The first batch from Mike has shipped! I hope to receive them this week and will get them straight out to those that have already placed orders.

December 2009 : Beta release 1.0b-beta integrates new version of libnfc wrapper (pynfc ver 0.2), which works with the latest libnfc SVN repo (r245).

November 2009: Release 1.0a  - Started integrating Nick von Dadelszen's libnfc wrapper so we can support the new generation of usb stick readers which are practically given away with digital cash products such as Snapper. I've also done a lot of tidying up of the Mifare key handling code (the KeyA and KeyB stuff was probably some of the earliest code I wrote on this project, and was pretty broken!), as I'm starting to see a lot of live security issues with Mifare cards and their use in applications such as hotel keys etc., so I've added copy/clone functionality to readmifaresimple.py (note that it's not capable of creating a true clone as we can't set the UID, but we can copy all data blocks and set keys).

February 2009: Finally got around to writing some more detailed documentation, and also got NXP PN532 chips to run in emulator mode. Documentation to do this was released by NXP under NDA, but they have now given me permission to publish code based on that documentation, so I'm able to release two new tools:

  pn532emulate.py - sets up the emulator and processes one command.

  pn532mitm.py - 'pn532 man-in-the-middle', which will drive two readers: one as an emulator and one as a reader, and will log all traffic that flows between them. Additionally, you can seperate the reader and emulator onto two different machines, and relay the traffic via TCP.

I've also added a tool for reading HID ProxCard IDs.

January 2009: 0.1w released - various fixes to mrpkey.py and new jcoptool.py

January 2009: RANDOM_UID mode available on JCOP cards. These cards will present a random UID instead of a fixed one, as per ICAO 9303 requirements for Machine readable Travel Documents. See Hardware section for more details.

January 2009: version 0.1v released with source of JAVA applet for JCOP card.

November 2008: version 0.1u released with support for JCOP Mifare emulation. Also, IAIK DemoTag 13.56MHz emulators now available.

October 2008: version 0.1t released with support for JCOP Machine Readable Travel Documents (vonJeek emulator and JMRTD - A Free Implementation of Machine Readable Travel Documents).

April 2008: Windows distribution of RFIDIOt now available! See download section for where to get it.

February 2008 - 'ChAP.py' released... first cut of EMV Chip And PIN credit card reading script (currently for PC/SC readers only).
13th April 2008 - version 0.1b is out. Run 'ChAP.py -h' for features. Download it here.

An all-in-one reader/writer is now available: the LAHF is a Low And High Frequency device incorporating both the ACG LF Multitag and the ACG HF Multi-ISO into a single unit. Each reader presents it's own virtual serial interface to the O/S via a single USB connection, so can still be independantly addressed by software. See the hardware section for more details.

Also, following a re-design, the USB version of the ACG HF Multi-ISO is now the same price as the serial version.

Contents


What is RFIDIOt?
What does it do?
Hardware
What can it read or write?
What standards does it support?
Download
Documentation
Licensing
Contribute
Tag Gallery
e-Passports
Passport Certificates
Passport Profiling
Technical Notes
RFID Blocking
In The News
Who am I?

What is RFIDIOt?

RFIDIOt is an open source python library for exploring RFID devices. It's called "RFIDIOt" for two reasons:

  1. I like puns. This one stands for "RFID IO tools"
  2. Since I haven't done any serious programming for a long time, I felt like an idiot having to learn a whole new language and the code probably looks like it's written by an idiot. However, python rocks, so it was worth it!

What does it do?

It currently drives a range of RFID readers made by ACG, called the HF Dual ISO and HF Multi ISO, which are both 13.56MHz devices, and the LF MultiTag which is 125/134.2kHz. Frosch Hitag reader/writers are also now supported. There's no reason it couldn't work with others, these are just the first ones I got my hands on, and since they present themselves to the O/S as standard serial devices without having to install any drivers, it made interfacing very simple (but see the Technical Note section below as I've had some issues recently). I have written some example programs to read/write tags and have started on the library routines to handle the data structures of specific tags like MIFARE®. It is far from complete but I thought I'd follow the "publish early, publish often" philosophy on this one...

PC/SC (MUSCLE) devices, such as the Omnikey CardMan are also supported. I am curently testing with a CardMan 5321.

Hardware


I get lots of emails asking where to buy readers/writers, so if you are looking for hardware, RFIDIOt custom built kit and other items I use for testing can be purchased here. These are RFIDIOt compatible read/write devices (where appropriate), and come with power cables and a full year's no- quibble 'fix or replace' warranty.

All prices exclude delivery which will be calculated at checkout. If you are outside the UK, please add £8 per item using the 'Overseas Postage' item at the bottom of the table. All orders will be sent via UK Post Office tracked services.

Standard Reader / Writers Solution Graphics
Type Frequency Interface Supported Tag Types Image Price Purchase
ACG HF Serial 13.56 MHz Serial RS232 ISO 14443 A/B, ISO 15693, ISO 18000-3, NFC, I-CODE ACG Serial
Out of stock!
ACG HF USB 13.56 MHz USB ISO 14443 A/B, ISO 15693, ISO 18000-3, NFC, I-CODE
ACG HF USB
Out of stock!
ACG LAHF USB 125/134.2 kHz

&

13.56 MHz
USB EM4x02
EM4x50
EM4x05 (ISO 11784/5 FDX-B)
Hitag 1 / 2 / S
Q5
TI 64 bit R/O & R/W
TI 1088 bit Multipage

ISO 14443 A/B, ISO 15693, ISO 18000-3, NFC, I-CODE
ACG HF USB
Out of stock!
OmniKey
Cardman 5321
13.56 MHz USB PC/SC ISO 14443 A/B
ISO 15693
HID iCLASS
+ ISO 7816 Smartcard
Omnikey Cardman 5321 Out of stock!
IAIK DemoTag 13.56 MHz Serial RS232
JTAG
ISP
ISO 15693
ISO 18000-3
NFC
ISO 14443A
IAIK DemoTag
Purchase direct from IAIK
ACG LF Serial 125 / 134.2 kHz Serial RS232 EM4x02
EM4x50
EM4x05 (ISO 11784/5 FDX-B)
Hitag 1 / 2 / S
Q5
TI 64 bit R/O & R/W
TI 1088 bit Multipage
ACG Serial LF Out of stock!
ACG LF USB 125 / 134.2 kHz USB EM4x02
EM4x50
EM4x05 (ISO 11784/5 FDX-B)
Hitag 1 / 2 / S
Q5
TI 64 bit R/O & R/W
TI 1088 bit Multipage
ACG LF USB Out of stock!
OmniKey
Cardman 5325 PROX
(READ ONLY)
125 kHz USB PC/SC HID Prox
 + ISO 7816 Smartcard
Omnikey Cardman 5325 Out of stock!
Frosch Hitag Serial 125 kHz Serial RS232 Hitag 1 / 2 / S Frosch Hitag Out of stock!
Frosch Hitag USB 125 kHz USB Hitag 1 / 2 / S
Frosch USB Out of stock!
Keyboard Wedge Verification LF Reader
(READ ONLY)
125 kHz USB Trovan 'Unique' / EM4x02 Unique USB keyboard wedge Out of stock!
Re-Writeable Q5 LF TAG blank

125 / 134.2 kHz n/a Trovan 'Unique' / ISO FDX-B / HID Prox / other Q5 TAG
£5
Re-Writeable T55x7 LF TAG blank

125 / 134.2 kHz n/a Trovan 'Unique' / ISO FDX-B / HID Prox / other Q5 TAG
£5
NXP JCOP31 36K
Smartcard
13.56 MHz NFC SmartCard ISO 7816 / Global Platform
Mifare
JAVACARD
£8
NXP JCOP31 36K RANDOM_UID
Smartcard
13.56 MHz NFC SmartCard ISO 7816 / Global Platform
Mifare
JAVACARD
£12
NXP JCOP J3A081 80K
Smartcard
13.56 MHz NFC SmartCard ISO 7816 / Global Platform
Mifare
JMRTD
vonJeek
JAVACARD
£16
NXP JCOP J3A081 80K RANDOM_UID
Smartcard
13.56 MHz NFC SmartCard ISO 7816 / Global Platform
Mifare
JMRTD
vonJeek
JAVACARD
£26
RFIDler 125-134 KHz USB Serial
UART
LF
RFIDler
Out of Stock!
YARD Stick One
281 - 962 MHz
USB
RF RX/TX
GoodFET
GPIO

n/a
yardstick-one
Out of Stock!
Ubertooth One
2.4 GHz
USB
RF RX/TX
JTAG

n/a
ubertooth-one
Out of Stock!
Throwing Star LAN Tap Kit
Ethernet
RJ45

n/a
lantap
Out of stock!
Throwing Star LAN Tap PRO
Ethernet
RJ45

n/a
lantap-pro
OUT OF STOCK
Overseas Postage n/a n/a n/a n/a £8
per item

What can it read or write?

A London Transport Oyster card is based on a MIFARE® Standard card, so if you already have an Oyster card you have something you can play with. The sample program bruteforce.py can be run against it, and it will try to log in to sector 0 by choosing random numbers as the key. This is about as likely to work as winning the national lottery three times in a row, but what the hell? Odds like that don't stop people playing the national lottery three times in a row... If you "win" please let me know! :)

See the 'Tag Gallery' section below for more detailed information on each of the devices I've seen so far.

What standards does it support?

The Dual ISO reader will read (and write) 13.56MHz devices with the following tags:

  MIFARE® Standard, MIFARE® 4k, MIFARE® Pro, MIFARE® Ultralight, MIFARE® DESFIRE, MIFARE® SmartMX
  SLE 55Rxx, SLE 66CL160S, SLE 66CLX320P, SR176, SRIX4K
  ISO14443A Tags
  ISO14443B Tags
  Jewel Tag (IRT0302B11 KSW DIY Eng. Sample)
  Sharp B
  ASK GTML2ISO
  TOSMART P032/P064

In addition to these, the Multi ISO will also handle ISO 15693, ISO 18000-3, NFC enabled, ICODE standards, specifically:

  I-CODE SLI (SL2 ICS 20)
  I-CODE EPC (SL2 ICS 10)
  I-CODE UID (SL2 ICS 11)
  I-CODE
  NFC (Reader To Tag Mode)
  SLE 55Rxx
  SRF55VxxP+S
  SLE 66CL160S
  SLE 66CLX320P
  SR176
  SRIX4K
  LRI 64
  LRI 512
  EM4135
  KSW Temp Sens ®
  Tag-it™ HF-I Standard
  Tag-it™ HF-I Pro
  ASK GTML
  ASK GTML2ISO

So far I have played with MIFARE® Standard (1K) and MIFARE® 4k and have obtained some MIFARE® DESFIRE cards but have not yet done anything with them.


The LFX will read/write 125kHz devices with the following tags:

  EM4x02
  EM4x50
  EM4x05 (ISO 11784/5 FDX-B)
  Hitag1
  Hitag2
  HitagS
  Q5
  TI-RFID SYSTEMS 64 bit R/O & R/W
  TI-RFID SYSTEMS 1088 bit Multipage

  The Q5 and Hitag2 can be programmed to emulate 'Unique' / EM4x02 and FDX-B / EM4x05 standards.
 
The Frosch will read/write:

  Hitag 1
  Hitag 2
  Hitag S

  The Hitag2 can be programmed to emulate 'Unique' / EM4x02 and FDX-B / EM4x05 standards.

Download

Code lives at https://github.com/AdamLaurie/RFIDIOt and is always a work in progress!

For the ACG or Frosch readers you'll need Chris Liechti's excellent pySerial module, and for PC/SC support you'll also need pyscard and PCSC-Lite.

If your python distro doesn't include Crypto, you'll need pycrypt too, and, if not already included, you'll also need to install Imaging.

If you want to extract the public keys from e-passports you'll need a local install of OpenSSL.

Licensing

The library is free for non-commercial use under the terms of the GPL (full terms in header of each module). For all other purposes please get in touch. My contact details are at the bottom of the page.

Contribute

If you'd like to contribute, please play with it and send me patches/comments/RFID devices/beer/money/loose women etc. You can mail me at: adam (at) algroup.co.uk, or you can make a paypal donation by clicking this button:  

Tag Gallery

EM 4x05
VeriChip
EM 4x50
EM 4x02
Trovan/Unique
Q5
Hitag2
Mifare 1K
Mifare 4K
Mifare Ultralight
ISO 14443 (e-Passport)
ISO 15693

The EM4x05 range implement the animal tagging standard ISO-11784 'Radio-frequency identification of
animals - Code structure' and ISO-11785 'Radio-frequency identification of animals - Technical concept' (also known as FDX-B).  These chips are ID-only transponders, operating at 134.2kHz and storing 128 bits of data, 64 bits of which are the ID:

  Bit 1:              'Animal Flag' - Animal or Non-Animal application indicator
  Bits 2 - 15:      Reserved Field - RFU
  Bit 16:             Data Block Flag - Indicates if more detailed data is also stored on this chip
  Bits 17 - 26:    Country Code - 3 digit country code as defined by ISO-3166, or manufacturer code by icar.org
  Bits 27 - 64:    National ID - Unique ID assigned by manufacturer / supplier
 
Q5 or Hitag2 tags can be programmed to emulate an EM4x05 using the fdxbnum.py program, and the ID set to any value.

Security warning: if you have a security system, such as building access control, that relies solely on the ID of an EM4x05 type token, you may want to test that it cannot be fooled by a Q5 or Hitag2 programmed as a clone of a valid token.

The implantable VeriChip appears to be an EM4x05:

VeriChip

It can be read with the readlfx.py command:

This one is a sample in a paperweight from VeriCorp. Note that the Application Identifier is out of spec according to ISO-11784 as it uses some reserved bits:
 readlfx v0.1e (using RFIDIOt v0.1g)
reader: LFX 1.0 (serial no: 00000000)
Card ID: 0651A63EA66F0329
Tag type: EM 4x05 (ISO FDX-B)
Application Identifier: 94c0
Country Code: 985 (MANUF: Destron Fearing / Digital Angel Corporation)
National ID: 23561865824
This is Henry Porter's implant, which he had done for a TV Documentary. Note that this time they've used a 4-digit country code instead of the standard 3 digits as specified by ISO-3166 and icar.org:
 readlfx v0.1e (using RFIDIOt v0.1g)
reader: LFX 1.0 (serial no: 00000000)
Card ID: 77E5000001FF0001
Tag type: EM 4x05 (ISO FDX-B)
Application Identifier: 8000
Country Code: 1022 (UNREGISTERED MANUF: VeriChip Corporation)
National ID: 42990

This is an EM 4x50 based ski pass from Verbier, circa 1999:

Verbier Ski Pass FrontVerbier Skip Pass Back

It can be read with the readlfx.py command:

  readlfx v0.1 (using RFIDIOt v0.1b)
  reader: LFX 1.0 (serial no: 00000000)
  Card ID: TDE2A3F00

    sector 01:  00000000
    sector 02:  1A1F0000
    sector 03:  00100100
    sector 04:  0022181A
    sector 05:  00000000
    sector 06:  00000000
    sector 07:  00000000
    sector 08:  00000000
    sector 09:  00000000
    sector 0a:  00000000
    sector 0b:  00000000
    sector 0c:  00000000
    sector 0d:  00000000
    sector 0e:  00000000
    sector 0f:  00000000
    sector 10:  00000000
    sector 11:  00000000
    sector 12:  00000000
    sector 13:  00000000
    sector 14:  00000000
    sector 15:  00000000
    sector 16:  00000000
    sector 17:  00000000
    sector 18:  00000000
    sector 19:  00000000
    sector 1a:  8022CABE
    sector 1b:  CCCC7C19
    sector 1c:  E3E77080
    sector 1d:  B1A65199
    sector 1e:  8453AFB9
    sector 1f:  E2876F65
    sector 20:  DE2A3F00
    sector 21:  3210003B
    sector 22:  Read error: R

EM H4102 keyfob TAG:

Unknown ID Tag

The ID can be read using cardselect.py:

  cardselect v0.1a (using RFIDIOt v0.1b)
  reader: LFX 1.0 (serial no: 00000000)
  Card ID: U2008BCFAF8

These are also sold by Trovan under the brand name 'Unique', and the ID can be decoded with readlfx.py:

trovan unique

 readlfx v0.1c (using RFIDIOt v0.1f)
reader: LFX 1.0 (serial no: 00000000)
Card ID: 2008BCFAF8
Tag type: EM 4x02
Unique ID: 04103d5f1f
Trovan also provide these as a 'Human Implantable' chip.

trovan implantable

At shmoocon in March 2007, I sucessfully cloned a human with a 'Unique' implant and was able to unlock his laptop (thanks Larry).

Q5 or Hitag2 tags can be programmed to emulate an EM4x02 using the unique.py program (in fact, that is the Q5 default mode), and the ID can be set to any value.

Security warning: if you have a security system, such as building access control, that relies solely on the ID of an EM4x02 type token, you may want to test that it cannot be fooled by a Q5 programmed as a clone of a valid token.

Q5

The Q5 is a 'smart' tag, capable of emulating other standard tags, including the ID number. It does this by allowing specification of various parameters such as modulation, bit rate etc. By setting the right configuration and storing and transmitting the appropriate bit pattern, a reader will be fooled into thinking it's seen the corresponding tag type and specific UID. So far I have implemented emulation of EM 4x02 and  EM 4x05 tags, using the unique.py and fdxbnum.py programs respectively.

Once programmed, a Q5 tag can be reverted to it's default mode with the q5reset.py program (currently only supported on ACG hardware).

They come in a huge variety of form factors, so it's quite likely you'll be able to find a blank that matches the tag you're trying to emulate:

Q5 ClamshellQ5 injectableQ5 LaminateQ5 nailQ5 wristbandq5 volcanoQ5 keyfobq5 glass

Hitag2

The Hitag2 is very similar to the Q5 in that it comes in a variety of form factors, and can be programmed to emulate other tag types. So far I have implemented emulation of EM 4x02 and  EM 4x05 tags, using the unique.py and fdxbnum.py programs respectively.

Once programmed, a Hitag2 tag can be reverted to it's default mode with the hitag2reset.py program (currently only supported on Frosch hardware).

Renault Laguna key

The Renault Laguna 'key' appears to be a Hitag2.


Mifare 1K promotional card:

Guinness MIFARE 1K

Contents can be read with readmifare1k.py:
(Note the login failure on sector 7 - this must be where they store confidential data)

readmifare1k v0.1b (using RFIDIOt v0.1d)
reader: Dual 2.2 (serial no: 47050005)
Card ID: 1472F66F

MIFARE data (keytype FF):
        Serial number:          1472F66F
        Check byte:             FF
        Manufacturer data:      88040047C11DB649003905

 sector 00: Keytype: FF Login OK. Data:

  1472F66FFF88040047C11DB649003905 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 01: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 02: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 03: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 04: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 05: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 06: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 07: Keytype: FF Login failed
 sector 08: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 09: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 0a: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 0b: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 0c: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 0d: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 0e: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF078069FFFFFFFFFFFF
  Access Block User Data Byte: 69

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

 sector 0f: Keytype: FF Login OK. Data:

  00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 000000000000FF0780BCFFFFFFFFFFFF
  Access Block User Data Byte: BC

        Key A (non-readable):   000000000000
        Key B:                  FFFFFFFFFFFF
        Access conditions:      FF0780
                MIFAREC1:       0
                MIFAREC2:       0
                MIFAREC3:       8
                MIFAREblock0AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock1AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock2AC: 000
                        Read: KEYA/B, Write: KEYA/B, Increment: KEYA/B, Decrement/Transfer/Restore: KEYA/B (transport configuration)
                MIFAREblock3AC: 001
                        Write KeyA: KEYA, Read Access bits: KEYA, Write Access bits: KEYA, Read KeyB: KEYA, Write KeyB: KEYA (KEYB readable, transport configuration)

Mifare Standard 4K:

Amsterdam Mifare 4K

The Amsterdam rechargable public transport system 'ov-chipkaart' is a Mifare 4K. The sectors are locked so it cannot be read, but it can be identified with isotype.py:

$ ./isotype.py -r2
isotype v0.1g (using RFIDIOt v0.1p)
Reader: PCSC OMNIKEY CardMan 5x21 00 01

ID: 8422539A
Tag is ISO 14443 A, part 3


ATR: 3B8F8001804F0CA0000003060300020000000069
3B Initial Header
8 No TA1, TB1, TC1 only TD1 is following
F 15 bytes historical data follow
8 No TA2, TB2, TC2 only TD2 is following
0 T = 0
0 No TA3, TB3, TC3, TD3 following
1 T = 1
Detected STORAGECARD
Historical: 804F0CA00000030603000200000000
80 Status indicator may be present (COMPACT-TLV object)
4F Application Identifier presence indicator
0C 12 bytes follow
RID: A000000306 PC/SC Workgroup
PIX: 03000200000000
SS: 03 ISO 14443 A, part 3
Name: 0002 Mifare Standard 4K
RFU: 00000000
Checksum TCK: 69 (OK)
Mifare Ultralight:

Amsterdam Mifare Ultralight

The Amsterdam disposable public transport 'ov-chipkaart' is a Mifare Ultralight. As the sectors are not locked, they can be read with readtag.py:

$ ./readtag.py 
readtag v0.1b (using RFIDIOt v0.1p)
Reader: ACG MultiISO 1.0 (serial no: 34060217)

ID: 04A6B0D9D20280
Data:
Block 00: 04A6B09AD9D20280894800F000000000
Block 01: D9D20280894800F000000000FFFFFFFF
Block 02: 894800F000000000FFFFFFFF00000000
Block 03: 00000000FFFFFFFF0000000000000000
Block 04: FFFFFFFF000000000000000000000000
Block 05: 000000000000000000000000C8001002
Block 06: 0000000000000000C8001002077D2170
Block 07: 00000000C8001002077D21702034F309
Block 08: C8001002077D21702034F30959DA9EE8
Block 09: 077D21702034F30959DA9EE8256C0071
Block 0a: 2034F30959DA9EE8256C0071BF19390A
Block 0b: 59DA9EE8256C0071BF19390A88A049D6
Block 0c: 256C0071BF19390A88A049D613B8CD71
Block 0d: BF19390A88A049D613B8CD7104A6B09A
Block 0e: 88A049D613B8CD7104A6B09AD9D20280
Block 0f: 13B8CD7104A6B09AD9D20280894800F0

Identifying it with isotype.py on a PC/SC reader shows some more information on the chip itself:

$ ./isotype.py -r2
isotype v0.1g (using RFIDIOt v0.1p)
Reader: PCSC OMNIKEY CardMan 5x21 00 01

ID: 04A6B0D9D20280
Tag is ISO 14443 A, part 3


ATR: 3B8F8001804F0CA0000003060300030000000068
3B Initial Header
8 No TA1, TB1, TC1 only TD1 is following
F 15 bytes historical data follow
8 No TA2, TB2, TC2 only TD2 is following
0 T = 0
0 No TA3, TB3, TC3, TD3 following
1 T = 1
Detected STORAGECARD
Historical: 804F0CA00000030603000300000000
80 Status indicator may be present (COMPACT-TLV object)
4F Application Identifier presence indicator
0C 12 bytes follow
RID: A000000306 PC/SC Workgroup
PIX: 03000300000000
SS: 03 ISO 14443 A, part 3
Name: 0003 Mifare Ultra light
  RFU: 00000000
Checksum TCK: 68 (OK)
Amsterdam University used RFIDIOt to discover some security flaws in this system.

ISO 14443 (type A) UK Passport:

UK Passport CoverUK Passport Chip

The ID can be read with cardselect.py, but it returns a different number every time (I ran a slightly modified version that does multiple selects):

cardselect v0.1b (using RFIDIOt v0.1d)
reader: Dual 2.2 (serial no: 47050005)
Card ID: 0814252A
Card ID: 0852FB48
Card ID: 0813F98C
Card ID: 0894B632
Card ID: 08735DEB
Card ID: 083D756E
Card ID: 08AA9CC0
Card ID: 08571F6C
Card ID: 0850AAC2
Card ID: 0807D5F8

This means the tag is generating it's ID on the fly, which would be a very useful feature for, errr... security auditing tags... :)

The leading '08' of the ID indicates a random UID as per ISO-14443 part 3 (thanks to Henryk Plötz for pointing this out), and the rest of the digits are a pseudo-random sequence - if you'd like to have a go at working it out, here are dumps of three sessions containing a total of 19,658 select operations. Note that although they were all taken within a few minutes of each other, there were a number of individual select commands issued between each session. The passport was kindly provided by the No2ID campaign. This file contains 1,558,261 contiguous select operations from a different passport, serial number starting '108'. 

I have also been working on the code to implement the PKI for ICAO 9303, which will allow logging-in to the chips:

$ ./mrpkey.py TEST
mrpkey v0.1 (using RFIDIOt v0.1e)
reader: Dual 2.2 (serial no: 47050005)

Test MRZ: L898902C<3UTO6908061F9406236ZE184226B<<<<<14
Passport number: L898902C<
Check digit: 3
Nationality: UTO
Date Of Birth: 690806
Check Digit: 1
Sex: F
Expiry: 940623
Check Digit: 6
Optional: ZE184226B<<<<<
Check Digit: 1
Composite Check Digit: 4

Generate local keys:

Key MRZ Info (kmrz): L898902C<369080619406236
Kseed (SHA1 hash digest of kmrz): 239ab9cb282daf66231dc5a4df6bfbae

KENCa (encryption key A digest): ab94fdecf2674fdf
KENCb (encryption key B digest): b9b391f85d7f76f2

KMACa (Message Authentication Code A digest): 7962d9ece03d1acd
KMACb (Message Authentication Code B digest): 4c76089dce131543

Generate local random Challenge (rnd_ifd): 781723860C06C226
Generate local random Challenge (Kifd): 0B795240CB7049B01C19B33E32804F0B

S: 781723860c06c2264608f919887022120b795240cb7049b01c19b33e32804f0b
Kenc: ab94fdecf2674fdfb9b391f85d7f76f2
Eifd: 72c29c2371cc9bdb65b779b8e8d37b29ecc154aa56a8799fae2f498f76ed92f2
Kmac: 7962d9ece03d1acd4c76089dce131543
Mifd: 5f1448eea8ad90a7
cmd_data: 72c29c2371cc9bdb65b779b8e8d37b29ecc154aa56a8799fae2f498f76ed92f25f1448eea8ad90a7

Auth Response: 46B9342A41396CD7386BF5803104D7CEDC122B9132139BAF2EEDC94EE178534F2F2D235D074D7449
Auth message: 46B9342A41396CD7386BF5803104D7CEDC122B9132139BAF2EEDC94EE178534F
Auth MAC: 2F2D235D074D7449
In this case I've specified 'TEST' as the MRZ data, in which case the mrpkey.py program uses the worked-up example from the ICAO 9303 standard. Specifying genuine MRZ data will attempt authentication to a real passport (which has succeeded on every passport I've tried so far):
mrpkey v0.1c (using RFIDIOt v0.1g)
reader: Dual 2.2 (serial no: 47050005)

Passport number: 108nnnnnn
Check Digit: 6
Nationality: GBR
Date Of Birth: 90nnnn
Check Digit: 2
Sex: M
Expiry: 160810
Check Digit: 4
Optional: <<<<<<<<<<<<<<
Check Digit: 0
Composite Check Digit: 8

Generate local keys:

Key MRZ Info (kmrz): 108nnnnnnn90nnnn21608104

Select Passport Application (AID): OK
Select Master File: Basic Access Control enforced!
Generate local random Challenge (rnd_ifd): 4c05dcf71bcc0510
Generate local random Challenge (Kifd): e2ae78e4d5752cc1535c3567c77f7a2c

Authenticating: OK

Generate session keys:

Kifd XOR Kicc (kseed): 8923c07565483c2ef21a0935d62ca1d3
Session Key ENC: 166b0404b5da98fde6970162efab26d3
Session Key MAC: 0457834034c4f798451a07abb3235249

Calculate Send Sequence Counter:

SSC: 7ccd4bba1bcc0510
60145f01
File Length: 22
Reading: 00000
EF.COM: Length: 20
Tag: 5f01 (LDS Version)
Length: 4
Data: 30313037
Tag: 5f36 (Unicode Version)
Length: 6
Data: 303430303030
Tag: 5c (Tag List)
Length: 2
Data Group: 61 (EF.DG1 Data Recorded in MRZ)
Data Group: 75 (EF.DG2 Encoded Identification Features - FACE)
EF.COM stored in /tmp/EF_COM.BIN

Select EF.SOD: File Length: 1929
Reading: 00000
EF.SOD stored in /tmp/EF_SOD.BIN

Select DG1:
615b5f1f
File Length: 93
Reading: 00000
EF.DG1 stored in /tmp/EF_DG1.BIN
EF.DG1: Data Length: 88
Decoded Data: P<GBRLAURIE<<xxxxxxxxxx<xxxxxxxxx<xxxxx<<<<<108nnnnnnnGBR90nnnn2M1608104<<<<<<<<<<<<<<08
Document code: P<
Issuing State or organisation: GBR
Name: LAURIE<<xxxxxxxxxx<xxxxxxxxx<xxxxx<<<<<
Passport Number: 108nnnnnn
Check Digit: 6
Nationality: GBR
Date of Birth: 90nnnn
Check Digit: 2
Sex: M
Date of Expiry: 160810
Check Digit: 4
Personal Number or other optional elements: <<<<<<<<<<<<<<
Check Digit: 0
Composite Check Digit: 8

Select DG2:
File Length: 20028
Reading: 00000
EF.DG2: JPEG image stored in /tmp/EF_DG2.JPG
EF.DG2 stored in /tmp/EF_DG2.BIN
Note that I have obscured some of the data to respect the passport owner's privacy.

The latest version produces prettier output:

Phil Booth passport

Phil Booth of No2ID kindly gave his permission for his data to be reproduced here.

I must express my gratitude to Marc Witteman of Riscure for his invaluable help in interpreting the standards, particularly for pointing out the hidden gems in here.

Passport Certificates


I have started compiling a collection of digital certificates stored on passports and am always pleased to receive ones I haven't already got, so please email me yours if it's not already here.

The ICAO Public Key Directory (PKD) can be found here.

Passport profiling

Australian passports are interesting in that they have a couple of unusual features which could combine to make them unique.

They break ISO-14443 by not honouring the first two bytes of the random ID field, which should be '08':

multiselect v0.1a (using RFIDIOt v0.1g)
reader: Dual 2.2 (serial no: 47050005)
Card ID: 3F14252A
Card ID: 1A52FB48
Card ID: E713F98C
Card ID: 2B94B632
Card ID: 77735DEB
Card ID: 0B3D756E

Also, although they do implement Basic Access Control, it is done by giving a return value of 69 82 - 'Security status not satisfied' when EF.COM is read, rather than when it is first selected. This is not a major issue, and is actually compliant according to the ICAO 9303 Supplement section S1.0-20041220-LDS0028, but it does mean that the contents of the passport could be iterated prior to authentication, in as much as it could be determined which files (but not their contents) were stored on the chip based on the return value being equal to a successful select or file not found. 

These two features could potentially be combined to profile the passport and determine that it was probably an Australian issue without any other prior knowledge.

More worryingly, the Italian passport does not use random UIDs, so the passport is not only identifiable as Italian, but individuals can be discriminated once their UID is known.

American passports are interesting as they are the only ones that I've seen so far that have shielding in them (thanks to deviant for the video). They also fail to honour the random ID bytes, and store two extra data elements - DG11 and DG12: ' Additional Personal Detail(s)' .

I am currently having difficulty reading French and Irish passports, but Norwegian and German worked just fine, although the German passport uses a different image format (JP2).

ISO 15693:

Texas Instrument:

ISO 15693 Hotel Key

This hotel key is made by Texas Instrument:

$ ./isotype.py 
isotype v0.1g (using RFIDIOt v0.1p)
Reader: ACG MultiISO 1.0 (serial no: 34060217)

ID: E0078151C9B41427
Tag is ISO 15693
Manufacturer: Texas Instrument
The standard doesn't specify what block size the device is - that's left up to the manufacturer. In this case, the 4 byte data blocks can be read with readtag.py:

$ ./readtag.py 
readtag v0.1b (using RFIDIOt v0.1p)
Reader: ACG MultiISO 1.0 (serial no: 34060217)

ID: E0078151C9B41427
Data:
Block 00: 00000000
Block 01: 00000000
Block 02: 00000000
Block 03: 242738B0
Block 04: 096C2A48
Block 05: 00005091
Block 06: 8F4113B2
Block 07: 21764613
Block 08: 000074E9
Block 09: 00000000
Block 0a: 00000000
Block 0b: 00000000
Block 0c: 00000000
Block 0d: 00000000
Block 0e: 00000000
Block 0f: 00000000
Block 10: 00000000
Block 11: 00000000
Block 12: 00000000
Block 13: 00000000
Block 14: 00000000
Block 15: 00000000
Block 16: 00000000
Block 17: 00000000
Block 18: 00000000
Block 19: 00000000
Block 1a: 00000000
Block 1b: 00000000
Block 1c: 00000000
Block 1d: 00000000
Block 1e: 00000000
Block 1f: 00000000
Block 20: 00000000
Block 21: 00000000
Block 22: 00000000
Block 23: 00000000
Block 24: 00000000
Block 25: 00000000
Block 26: 00000000
Block 27: 00000000
Block 28: 00000000
Block 29: 00000000
Block 2a: 00000000
Block 2b: 00000000
Block 2c: 00000000
Block 2d: 00000000
Block 2e: 00000000
Block 2f: 00000000
Block 30: 00000000
Block 31: 00000000
Block 32: 00000000
Block 33: 00000000
Block 34: 00000000
Block 35: 00000000
Block 36: 00000000
Block 37: 00000000
Block 38: 00000000
Block 39: 00000000
Block 3a: 00000000
Block 3b: 00000000
Block 3c: 00000000
Block 3d: 00000000
Block 3e: 00000000
Block 3f: 00000000

EM Microelectronic-Marin SA:


Ski Dubai

This ski pass is made by EM Microelectronic-Marin SA (the 'chip' in the top right of the lower image is just printed on):

$ ./isotype.py 
isotype v0.1g (using RFIDIOt v0.1p)
Reader: ACG MultiISO 1.0 (serial no: 34060217)

ID: E01694021602D1E8
Tag is ISO 15693
Manufacturer: EM Microelectronic-Marin SA

and has 8 byte blocks:

$ ./readtag.py 
readtag v0.1b (using RFIDIOt v0.1p)
Reader: ACG MultiISO 1.0 (serial no: 34060217)

ID: E01694021602D1E8
Data:
Block 00: 6D40F80000000000
Block 01: FFF0782201E87822
Block 02: 00000083000000B3
Block 03: 000000E300000000
Block 04: 0000000000000000
Block 05: 0000000000000000
Block 06: 0000000000000000
Block 07: 0000000000000000
Block 08: 0000000000000000
Block 09: 0000000000000000
Block 0a: 0000000000000000
Block 0b: 0000000000000000
Block 0c: 0000000000000000
Block 0d: 0000000000000000
Block 0e: 0000000000000000
Block 0f: 0000000000000000
Block 10: 0000000000000000
Block 11: 0000000000000000
Block 12: 0000000000000000
Block 13: 0000000000000000
Block 14: 0000000000000000
Block 15: 0000000000000000
Block 16: 0000000000000000
Block 17: 0000000000000000
Block 18: 0000000000000000
Block 19: 0000000000000000
Block 1a: 0000000000000000
Block 1b: 0000000000000000
Block 1c: 0000000000000000
Block 1d: 0000000000000000
Block 1e: 0000000000000000
Block 1f: 0000000000000000
Block 20: 0000000000000000
Block 21: 0000000000000000
Block 22: 0000000000000000
Block 23: 0000000000000000
Block 24: 0000000000000000

Technical Notes

pcmcia drivers

When I started this project I was running Ubuntu 5.10 and the ACG readers just plugged in and worked (actually, for some strange reason you had to plug them in, unplug them, and then re-plug them on my Panasonic CF-72 before it noticed them). However, I recently upgraded to 6.06 LTS and everything stopped working. After much research I found out what was wrong, so here it is, blow by blow, in case you have the same problem.


Driver does not load (i.e. /dev/ttyS1 does not get mapped). 'dmesg' shows the following (on a Dell Latitude):

[17212461.436000] pccard: PCMCIA card inserted into slot 0
[17212461.436000] cs: memory probe 0xef600000-0xfbffffff: excluding 0xef600000-0xfa7fffff
[17212461.440000] pcmcia: registering new device pcmcia0.0
On the Panasonic I also get this in dmesg:
[17212460.764000] cs: pcmcia_socket0: unable to apply power.
investigation (on the Dell) with pccardctl reveals (note you must be root or you will get misleading results):
# pccardctl info
PRODID_1="ACG AT"
PRODID_2="ACG RF PC Handheld Reader"
PRODID_3="1.1"
PRODID_4="4705000570 "
MANFID=015d,4c45
FUNCID=2
PRODID_1="O2Micro"
PRODID_2="SmartCardBus Reader"
PRODID_3="V1.0"
PRODID_4=""
MANFID=ffff,0001
FUNCID=255
# pccardctl status
Socket 0:
no card
Socket 1:
5.0V 16-bit PC Card
Subdevice 0 (function 0) [unbound]
and on the Panasonic:
# pccardctl info
PRODID_1="ACG AT"
PRODID_2="ACG RF PC Handheld Reader"
PRODID_3="1.1"
PRODID_4="4705000570 "
MANFID=015d,4c45
FUNCID=2
PRODID_1=""
PRODID_2=""
PRODID_3=""
PRODID_4=""
MANFID=0000,0000
FUNCID=255
# pccardctl status
Socket 0:
no card
Socket 1:
no card
Issuing the following command gets the card to fire up:
# pccardctl insert
At this point on the Panasonic my keyboard stopped working, presumably due to some driver conflict (but mouse etc. were fine, if a little slow), so I gave up and worked only on the Dell:
# pccardctl status
Socket 0:
5.0V 16-bit PC Card
Subdevice 0 (function 0) bound to driver "snd-pdaudiocf"
Socket 1:
5.0V 16-bit PC Card
Subdevice 0 (function 0) [unbound]
So we now have a functioning card, but bound to the wrong driver. Unplugging the card, removing the offending driver and replugging sorts that out:
# rmmod snd-pdaudiocf
# pccardctl status
Socket 0:
5.0V 16-bit PC Card
Subdevice 0 (function 0) bound to driver "serial_cs"
Socket 1:
5.0V 16-bit PC Card
Subdevice 0 (function 0) [unbound]
And we are back in business! :)

USB drivers

ACG USB devices use an FTDI serial converter,  so the ftdi_sio driver must be loaded. Linux kernel versions 2.6.17 and upwards will correctly detect the device and automatically load the driver, but for previous versions you will need to load it manually:
# modprobe ftdi_sio vendor=0x0403 product=0xdd20
If you are running Doze or Mac OS X, you may need to install the FTDI Virtual COM Port drivers, which be found here.
Under OS X, the virtual devices will be called '/dev/tty.usbserial-*'.

JCOP Tools

If you are playing with Java cards and developing under Linux, then, like me, you are probably having a nightmare trying to find the JCOPtools plugin for Eclipse... The Windows version is relatively easy to find, but will not install under linux. Actually, the code is the same, it's just the way it's been packaged that stops it installing. To fix this, do the following:

$ cd JCOPtools/features 
$ jar xvfz com.ibm.bluez.jcop.eclipse_3.1.2.jar
$ vi feature.xml
(remove the lines that say: os="win32" - there should be 2 of them)
$ jar cvMf com.ibm.bluez.jcop.eclipse_3.1.2.jar f* license.html

You have now repackaged the tools to allow installation on any platform. Exit Eclipse, go back in and try the install again. You will need to uncheck the "Ignore features not suitable for this platform" box before it will see any installable features (if someone figures out how to make this work without unchecking the box please let me know and I'll update these instructions).

RFID Blocking

The paranoid amongst you may want to do something about carrying these things around, and since I was sent some of these DIFRwear passport holders and wallets to test, and they seem to work, I thought I'd share... I tried both 125kHz and 13.56MHz tags with the ACG reader, and a more powerful pet-id system, and they blocked them both completely.

rfid shielded passport holder  rfid shielded wallets

If you click on the above images or link and then purchase anything, I will, in theory, receive a small commission. However, this does not mean I support or endorse these products in any way other than to accept their payment for what would otherwise be free advertising in return for making a statement of what I believe to be fact. If you object to this, then you can go direct to their site (difrwear.com) and buy your wallets free from the curse of having renumerated me.

I've also been sent some samples of the Secure Passport Sleeve and Secure Sleeve envelope style protecters from ID Stronghold. They appear to be made of a Tyvek material, with some kind of metal coating on the inside. I tested them with a UK passport and an Oyster card, which both operate at 13.56MHz, and they blocked them completely. However, my pet-id reader was able to read an FDX-B tag operating at 125kHz through the envelope, and the ACG LFX was still able to read my ski-pass, which is also a 125kHz device.

secure id sleevesecure id passport sleeve

You can, of course, simply make your own... It seems the tin-foil-hat brigade were right all along: wrapping your passport in a sheet of cooking foil does the job nicely! :)

In The News

November 2006:
December 2006:
January 2007:
March 2007:

April 2007:

June 2007:

July 2007:

August 2007:
February 2008:
April 2008:
August 2008:
September 2008:

October 2008:
August 2009:
December 2009:
February 2010:
April 2010:

Who are you anyway? 

You can reach me at: adam (at) algroup.co.uk

Copyright (c) 2006-2020 Adam Laurie. Page last updated Tuesday, 17th March, 2020.
Custom QR Code by Russ Cox