NFCPassportReader
此包处理使用 iOS 13 CoreNFC API 读取 NFC 允许的护照
版本 2(及主分支)现在使用 Swift Async/Await 进行通信。如果您需要更早版本的,请使用 1.1.9 或以下版本!
支持的功能
- 基本接入控制 (BAC)
- 安全消息
- 读取 JPEG 和 JPEG2000 格式下的 DG1(MRZ 数据)和 DG2(图像),DG7、DG11、DG12、DG14 和 DG15(也支持 SOD 和 COM 数据组)
- 被动认证
- 主动认证
- 芯片认证(测试了 ECDH DES 和 AES 密钥,实现了 DH DES AES 密钥,应该可以工作但尚未测试)
- PACE - 目前仅支持通用映射 (GM)
- 能够导出护照流并将其读回
- 使用 Async/Await
这还只是初期阶段 - 代码远非完美,还有一些粗糙的边缘 - 肯定存在错误,我相信我并不完美。
它可以很好地读取和验证我的护照(以及我已能测试的其他护照),然而您的结果可能会有所不同。
安装
Swift Package Manager (推荐)
NFCPassportReader 可以通过指向此仓库的 URL 使用 Swift Package Manager 安装。
CocoaPods(已弃用且不受支持)
使用CocoaPods进行安装,在Podfile中添加以下行
use_frameworks!
pod 'NFCPassportReader', git:'https://github.com/AndyQ/NFCPassportReader.git'
然后,运行以下命令
$ pod install
注意 - **不要使用Bitcode** - 这不受支持,并且已被苹果弃用
使用方法
要使用,首先需要创建护照MRZ密钥,该密钥包括护照号码、出生日期和有效期(包括校验和)。日期格式为YYMMDD
例如
<passport number><passport number checksum><date of birth><date of birth checksum><expiry date><expiry date checksum>
e.g. for Passport nr 12345678, Date of birth 27-Jan-1998, Expiry 30-Aug-2025 the MRZ Key would be:
Passport number - 12345678
Passport number checksum - 8
Date Of birth - 980127
Date of birth checksum - 7
Expiry date - 250831
Expiry date checksum - 5
mrzKey = "12345678898012772508315"
然后在PassportReader的实例上调用readPassport方法,传入mrzKey、要读取的数据组和完成块。
例如
passportReader.readPassport(mrzKey: mrzKey, tags: [.COM, .DG1, .DG2], completed: { (error) in
...
}
当前支持的数据组包括:COM、DG1、DG2、DG7、DG11、DG12、DG14(部分)、DG15和SOD
这样就会处理护照的读取和图像,并将一个带有TagError错误的完成块返回,如果没有错误则返回nil。
如果成功,passportReader对象将包含护照MRZ和护照Image字段的正确数据。
此外,您可以通过提供自定义DisplayMessage回调来自定义NFC会话读取器中显示的消息,例如仅覆盖初始请求以显示护照消息
passportReader.readPassport(mrzKey: mrzKey, tags: [.COM, .DG1, .DG2],
customDisplayMessage: { (displayMessage) in
switch displayMessage {
case .requestPresentPassport:
return "Hold your iPhone near an NFC enabled passport."
default:
return nil
}, completed: { (error) in
...
}
日志记录
在PassportReader中可以通过在创建时传入日志级别来启用额外的日志记录(非常详细):
let reader = PassportReader(logLevel: .debug)
注意 - 目前这只是在控制台上打印 - 我将在以后实现更好的日志记录 - 很可能是使用SwiftyBeaver
被动身份验证
被动身份验证现在是主库的一部分,可用来确保电子护照有效且未被篡改。
它需要一个来自主列表(可以是发布其主列表的国家或ICAO PKD存储库)的CSCA证书集(PEM格式)。有关如何获取和创建此文件的详细信息,请参阅脚本文件夹。
样本应用中包含的masterList.pem文件仅用于确保没有编译器警告,并且只包含一个自生成的PEM文件,无法验证任何内容!
样本应用
仓库中包含一个示例应用,展示了该功能的用法。
故障排除
- 如果在执行初始相互认证挑战时,你遇到带SW1代码0x63、SW2代码0x00和不提供信息的错误,那么这通常是因为你的MRZ密钥不正确,以及可能是因为你的护照号码不完全正确。如果护照号码中的MRZ包含一个 '<',则需要将其包含在MRZKey中 - 校验和也应正确计算。更多详细信息,请参阅ICAO 9303第11部分的App-D2文档(https://www.icao.int/publications/Documents/9303_p11_cons_en.pdf)
例如,如果MRZ底行的看起来是这样的:12345678<8AUT7005233M2507237<<<<<<<<<<<<<<06
在这种情况下,护照号码是12345678,但使用了一个额外的 '<' 填充。这需要在用于BAC的MRZ密钥中包含。例如,12345678<870052332507237将是使用的密钥。
待办事项
有许多事情我希望以无特定顺序实现
- 完成PACE身份验证(IM和CAM)
感谢
我想感谢passport(Jean-Francois Houzard和Olivier Roger - 无法找到他们的网站,但来自https://github.com/andrew867/epassportviewer)的初始化者,这个项目是基于他们的工作的。
YobiWiki上的ePassport部分(http://wiki.yobi.be/wiki/EPassport),这已经是一个无价的资源,特别是在被动认证方面。
感谢Marcin Krzyżanowski为他的OpenSSL-Universal仓库所作 contribution。