William Goodspeed 的又一个博客

使用 PN532 读取中华人民共和国护照

Published by goodspeed on February 20, 2024 in 默认分类.

本来是打算读身份证的,但发现身份证的读取是专有且受限的。护照有国际统一的标准,所以我对护照下手。

准备工作

护照(或者准确地说,电子护照: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

启动 pcscdifdnfc

# service pcscd restart
# ifdnfc-activate

尝试读取护照

20240220_221305_8835694907099940716.jpg

将护照背面的中心靠上位置贴于 PN532 上,然后运行命令:

$ pcsc_scan

你应该能找到你的护照(不知道为啥,它会觉得是 Spanish Passport)。

然后打开 cardpeek,选择名为 IFD-NFC 的读卡器。点击左上角的 Analyze 并选择 e-passport

它会要求你输入 MRZ (Machine Readable Zone, 机器可读区域) 中的第二行,这是因为电子护照使用 BAC (Basic access control)。MRZ 在护照姓名页的最下面,第一行有一堆 <

输入完 MRZ 的内容后稍等一会,cardpeek 就会读出护照上的内容。

20240220_23h54m59s_grim.png

里面都有什么?

读出来以后,可以看到 EF.DG1 中记录着 MRZ 的内容。MRZ 中记录着护照持有者的各种信息,具体解读方法见Wikipedia: 可机读护照

和其它一堆二进制数据与无法读取的部分。

EF.SOD 也很有意思,记录着发照机构相关内容:

20240221_00h02m15s_grim.png

读取持照人照片

护照里面有头像和指纹,读指纹肯定没啥戏,但头像还是可以的。在 EF.DG2 可以看到 Image Data,将十六进制的字符串保存到文件,然后转换为二进制:

$ xxd -r -p data.hex data.bin

你可以发现它的确是图像文件:

$ file data.bin 
data.bin: JPEG 2000 codestream

这个格式稍微有点特殊,但使用 gimp 可以顺利打开。


暂无评论

添加新评论




最近回复

分类