NFCPassportReader 2.1.1

NFCPassportReader 2.1.1

Andy Qua 维护。



  • 作者:
  • Andy Qua

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。