Skip to content
NFCPassportReader for iOS 13
Branch: master
Clone or download
AndyQ Added ability to lookup errors received from the passport - currently…
… just prints to logs not returned yet

Moved Sample app UI over to SwiftUI
Latest commit 1731f97 Jun 17, 2019


This package handles reading an NFC Enabled passport using iOS 13 CoreNFC APIS

Supported features:

  • Basic Access Control (BAC)
  • Secure Messaging
  • Reads DG1 (MRZ data) and DG2 (Image) in both JPEG and JPEG2000 formats

This is still very early days - the code is by no means perfect and there are still some rough edges - there ARE most definately bugs and I'm sure I'm not doing things perfectly.

It reads my passport (and others I've been able to test) fine, however your milage may vary.


To use, you first need to create the Passport MRZ Key which consists of the passport number, date of birth and expiry date (including the checksums). Dates are in YYMMDD format

For example:

<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"

Then on an instance of PassportReader, call the readPassport method passing in the mrzKey, and a completion block.

passportReader.readPassport(mrzKey: mrzKey, completed: { (error) in

This will then handle the reading of the passport, and image and will call the completion block either with an TagError error if there was an error of some kind, or nil if successful.

If successful, the passportReader object will then contain valid data for the passportMRZ and passportImage fields.


Additional logging (very verbose) can be enabled on the PassportReader by passing in a log level on creation: e.g.

let reader = PassportReader(logLevel: .debug)

NOTE - currently this is just printing out to the console - I'd like to implement better logging later - probably using SwiftyBeaver


There is a sample app included in the repo which demonstrates the functionality.

To do

There are a number of things I'd like to implement in no particular order:

  • Proper parsing of DG1 datagroup (MRZ data)
  • Ability to select which datagroups are read - currently both DG1 and DG2 are read
  • Ability to dump passport stream and read it back in


I'd like to thank the writers of pypassport (Jean-Francois Houzard and Olivier Roger - can't find their website but referenced from who's work this is based on.

You can’t perform that action at this time.