解析护照机读码的中文字符
2022-06-21 03:39:58

动机

刷小红书时看到一条使用虚假护照信息进行诈骗的帖子。评论区有网友指出了机读码对应的证件持有人姓名,虽然没有给出具体思路,但考虑到中国人姓名字符集的多样性,不难猜出这是某种国标汉字编码到 ASCII 字符的映射。

解析

如图所示,护照资料页下方的两行黑色 ASCII 字符串即为机读码 (Machine Readable Zone, MRZ)。其中位于第二行后半部分的、长度为 4 的整数倍的英文字符串是经过编码后的持有人姓名,最多可以储存三个汉字。将汉字的 GB2132 的每个 byte 的两位以十六进制分别映射到字母表中,即可获得对应机读码字符串。例如:"张" -> "\xd5\xc5" (GB2312) -> [d, 5, c, 5] (hex) -> [14, 6, 13, 6] (10) -> NFMF (MRZ)

可以通过下面的 Python 代码实现汉字与机读码互转。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import re


def encode(s: str) -> list[str]:
s = s.encode(encoding='gb2312').hex()
res = []
for c in s:
res.append(chr(ord('a') + int(c, base=16)))
return "".join(res).upper()


def decode(s: str) -> list[str]:
t = []
for c in s:
t.append(format((ord(c) - ord('A')), 'x'))
t = re.findall('.{1,2}', "".join(t))
res = []
for c in t:
res.append(int("0x" + c, 16))
return bytes(res).decode('gb2312')


print(encode('证'))
print(encode('件'))
print(encode('样'))


print(decode('NGKE'))
print(decode('LMPO'))
print(decode('NBPJ'))

注意

1980 年,中国发布了第一个汉字编码标准,也即 GB2312 ,全称 《信息交换用汉字编码字符集·基本集》,通常简称 GB (“国标”汉语拼音首字母), 共收录了 6763 个常用的汉字和字符,此标准于次年5月实施,它满足了日常 99% 汉字的使用需求。

由于有些汉字是在 GB2312 标准发布之后才简化的,还有一些人名、繁体字、日语和朝鲜语中的汉字也没有包括在内,所以,在 GB2312 的基础上添加了这部分字符,就形成了 GBK ,全称 《汉字内码扩展规范》,共收录了两万多个汉字和字符,它完全兼容 GB2312
GBK 于 1995 年发布,不过它只是 “技术规范指导性文件”,并不属于国家标准。

GB18030 全称《信息技术 中文编码字符集》 ,共收录七万多个汉字和字符, 它在 GBK 的基础上增加了中日韩语中的汉字 和 少数名族的文字及字符,完全兼容 GB2312,基本兼容 GBK。

by 彻底搞明白 GB2312、GBK 和 GB18030 - 知乎

查询字符编码时意外地发现 GBK 和 GB18030 对于 GB2312 完全兼容,因此上文给出的 Python 代码很不严谨,护照可能使用了 GB18030 作为机读码编码。

Prev
2022-06-21 03:39:58