使用 PN532 读取中华人民共和国护照
本来是打算读身份证的,但发现身份证的读取是专有且受限的。护照有国际统一的标准,所以我对护照下手。
准备工作
护照(或者准确地说,电子护照:E-passport)中的芯片与常见的 M1 卡(一般门禁卡)不同。读取这样的卡片(即智能卡:Smartcard)一般通过 PCSC/CCID 协议与读卡器通讯,并且主要使用「智能卡应用协议数据单元」(ADPU)与智能卡进行通讯。
PN532 读卡器模块很便宜,但是要使用 PN532 必须通过 I2C/SPI/UART(HSU) 发送其用户手册规定的命令。市售的 PN532 模块一般工作在 HSU (High Speed UART) 模式下,并通过上面的 ch341 芯片转成 USB 接口。
所以,我们让 PN532 可以通过 PCSC 协议通讯。这里,需要用到 ifdnfc
程序。主流发行版已经打包 PCSC 库,但不幸的是,没有 ifdnfc
,需要自行编译。
安装 Cardpeek
# apt install cardpeek
安装 PCSC 与 ifdnfc
安装 PCSC:
# apt install pcscd pcsc-tools libpcsclite-dev
安装 libnfc
:
# apt install libnfc-bin libnfc-dev
构建并安装 ifdnfc
:
$ git clone --depth=1 https://github.com/nfc-tools/ifdnfc
$ cd ifdnfc
$ autoreconf -vis
$ ./configure
$ make && sudo make install
配置 PCSC
要让 pcscd
可以成功与 PN532,我们需要先找到 PN532 的位置。反复插拔 PN532 几次,然后查看 dmesg
。你会看到类似下面的信息:
[ 8396.180095] usb 3-2: new full-speed USB device number 6 using xhci_hcd
[ 8396.329106] usb 3-2: New USB device found, idVendor=1a86, idProduct=7523, bcdDevice= 2.64
[ 8396.329122] usb 3-2: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[ 8396.329126] usb 3-2: Product: USB Serial
[ 8396.331080] ch341 3-2:1.0: ch341-uart converter detected
[ 8396.332075] usb 3-2: ch341-uart converter now attached to ttyUSB0
[11469.467062] usb 3-2: USB disconnect, device number 6
[11469.467587] ch341-uart ttyUSB0: ch341-uart converter now disconnected from ttyUSB0
[11469.467628] ch341 3-2:1.0: device disconnected
其中的 ttyUSBX
就是 PN532 串口设备的位置。随后我们配置 libnfc
,在 /etc/nfc/libnfc.conf
中追加这两行:
device.name = "IFD-NFC"
device.connstring = "pn532_uart:/dev/ttyUSBX"
然后可以试试 libnfc
能不能用。将随便一张 NFC 卡片置于 PN532 上,然后应该可以看到类似的内容:
# sudo nfc-list
nfc-list uses libnfc 1.8.0
NFC device: IFD-NFC opened
1 ISO14443A passive target(s) found:
ISO/IEC 14443A (106 kbps) target:
ATQA (SENS_RES): 00 04
UID (NFCID1): 42 d3 f0 bc
SAK (SEL_RES): 08
然后将 ifdnfc
配置为 PCSC 读卡器,创建 /etc/reader.conf.d/libifdnfc
:
FRIENDLYNAME "IFD-NFC"
LIBPATH /usr/local/lib/libifdnfc.so
CHANNELID 1
启动 pcscd
与 ifdnfc
# service pcscd restart
# ifdnfc-activate
尝试读取护照
将护照背面的中心靠上位置贴于 PN532 上,然后运行命令:
$ pcsc_scan
你应该能找到你的护照(不知道为啥,它会觉得是 Spanish Passport)。
然后打开 cardpeek
,选择名为 IFD-NFC
的读卡器。点击左上角的 Analyze 并选择 e-passport
。
它会要求你输入 MRZ (Machine Readable Zone, 机器可读区域) 中的第二行,这是因为电子护照使用 BAC (Basic access control)。MRZ 在护照姓名页的最下面,第一行有一堆 <
。
输入完 MRZ 的内容后稍等一会,cardpeek
就会读出护照上的内容。
里面都有什么?
读出来以后,可以看到 EF.DG1
中记录着 MRZ 的内容。MRZ 中记录着护照持有者的各种信息,具体解读方法见Wikipedia: 可机读护照。
和其它一堆二进制数据与无法读取的部分。
EF.SOD
也很有意思,记录着发照机构相关内容:
读取持照人照片
护照里面有头像和指纹,读指纹肯定没啥戏,但头像还是可以的。在 EF.DG2
可以看到 Image Data,将十六进制的字符串保存到文件,然后转换为二进制:
$ xxd -r -p data.hex data.bin
你可以发现它的确是图像文件:
$ file data.bin
data.bin: JPEG 2000 codestream
这个格式稍微有点特殊,但使用 gimp
可以顺利打开。