DOT iOS NFC library



DOT iOS NFC as a part of DOT iOS libraries family provides Travel Document NFC reader component. Supported documents are those, which implement Machine Readable Travel Document (MRTD) standards as specified by the International Civil Aviation Organization (ICAO).

Components overview

DOT iOS NFC provides a non-UI component for Travel Document reading. A client developers are supposed to build their own UI on top of this component.

List of Non-UI Components


Component for reading NFC enabled travel documents.


Component is distributed using Cocoapods with its dependencies stored in our public github repository. First step is to insert following line of code on top of your Podfile.

source ''

Then DOT iOS NFC dependency must be specified in Podfile. Dependencies of DOT iOS NFC will be downloaded alongside it.

source ''


target 'YOUR_TARGET' do

pod 'dot-nfc'


In case of problems with pod install, try to clone the private pod repository manually.

pod repo remove innovatrics
pod repo add innovatrics

Sample Project

Usage and configuration of DOT iOS NFC are demonstrated in DOT iOS Kit Sample demo project. To run the sample, you must install pods and then open DOTSample.xcworkspace.


  • Add capability to your Xcode target: Near Field Communication Tag Reading

  • DOT iOS NFC requires following keys in Info.plist:

<string>NFC tag to read NDEF messages into the application</string>



  • Xcode 11.4+

  • Framework supports iOS 13+. However, it can be added to projects with minimum deployment target starting from iOS 10.1. This allows you to put NFCReader code in @available block.

  • Swift or Objective-C support

  • CocoaPods

Framework currently does not support bitcode, i.e. it has flag ENABLE_BITCODE=NO. This is due to its OpenSSL dependancy, we are aiming to fix this in the near future.


String resources can be overridden in your application and alternative strings for supported languages can be provided following these two steps:

  1. Add your own Localizable.strings file to your project using standard iOS localization mechanism. To change a specific text override corresponding key in this Localizable.strings file.

  2. Set the localization bundle to the bundle of your application (preferably during the application launch in your AppDelegate).

import NFCReader

DotNfcLocalization.bundle = .main

Custom localization

You can override standard iOS localization mechanism by providing your own translation dictionary and setting the DotNfcLocalization.useLocalizationDictionary flag to true.

import NFCReader

guard let localizableUrl = Bundle.main.url(forResource: "Localizable", withExtension: "strings", subdirectory: nil, localization: "de"),
      let dictionary = NSDictionary(contentsOf: localizableUrl) as? [String: String]
else { return }

DotNfcLocalization.useLocalizationDictionary = true
DotNfcLocalization.localizationDictionary = dictionary
"nfc.pasport_reader.hint.beginReading" = "Hold your iPhone near an NFC enabled document.";
"nfc.pasport_reader.hint.multipleTagsFound" = "More than 1 tag was found. Please present only 1 tag.";
"nfc.pasport_reader.hint.tagNotFound" = "Missing tag. Please present 1 tag.";
"nfc.pasport_reader.hint.invalidTag" = "Tag not valid.";
"nfc.pasport_reader.hint.connectionError" = "Connection error. Please try again.";
"nfc.pasport_reader.hint.establishAccessControl" = "Establishing access control with the document...\n";
"nfc.pasport_reader.hint.readingData" = "Reading document data...\n";
"nfc.pasport_reader.hint.accessControlError" = "There was a problem establishing access control with the document.";
"nfc.pasport_reader.hint.readingCom" = "Reading COM...";
"nfc.pasport_reader.hint.readingSod" = "Reading SOD...";
"nfc.pasport_reader.hint.readingDG1" = "Reading DG1...";
"nfc.pasport_reader.hint.readingDG2" = "Reading DG2...";
"nfc.pasport_reader.hint.readingDG3" = "Reading DG3...";
"nfc.pasport_reader.hint.readingDG4" = "Reading DG4...";
"nfc.pasport_reader.hint.readingDG5" = "Reading DG5...";
"nfc.pasport_reader.hint.readingDG6" = "Reading DG6...";
"nfc.pasport_reader.hint.readingDG7" = "Reading DG7...";
"nfc.pasport_reader.hint.readingDG8" = "Reading DG8...";
"nfc.pasport_reader.hint.readingDG9" = "Reading DG9...";
"nfc.pasport_reader.hint.readingDG10" = "Reading DG10...";
"nfc.pasport_reader.hint.readingDG11" = "Reading DG11...";
"nfc.pasport_reader.hint.readingDG12" = "Reading DG12...";
"nfc.pasport_reader.hint.readingDG13" = "Reading DG13...";
"nfc.pasport_reader.hint.readingDG14" = "Reading DG14...";
"nfc.pasport_reader.hint.readingDG15" = "Reading DG15...";
"nfc.pasport_reader.hint.readingDG16" = "Reading DG16...";
"nfc.pasport_reader.hint.readingUnknown" = "Reading unknown data group...";

Reading Process

Travel document reading process consists of three steps: Access Establishment, Passive Authentication, Active Authentication.

Access Establishment

There are two Access Establishment protocols Basic Access Control - BAC and Password Authenticated Connection Establishment - PACE. DOT iOS NFC currently supports only BAC.


In order to access document using BAC, MRZ Key is required. This MRZ Key is created from document number, date of birth and date of expiry.


PACE is the newer and more secure version of Access Establishment protocols. It uses MRZ Key (weak password with low entropy) and generates cryptographically strong session keys.

Passive Authentication

The purpose of Passive Authentication is to validate the integrity of data stored on NFC chip. In other words, it verifies that data stored on NFC chip has not been altered. Passive Authentication has following steps:

  • extract and validate Document Signing Certificate with CSCA Certificates from master list

  • verify that Security Data (EF.SOD) has been correctly signed by Document Signing Certificate

  • verify that hashes stored in EF.SOD are valid, i.e. hashes stored in EF.SOD are equal to hashes computed from data groups present on the document

Active Authentication

The purpose of Active Authentication is to verify that document is genuine, i.e. it is not a copy. Active Authentication has following steps:

  • generate random challenge

  • request signature for this challenge from the NFC chip

  • verify signature using public key stored in Data Group 15 (DG15)

The public key stored in DG15 can be RSA or ECDSA. DOT iOS NFC currently supports only ECDSA.



This class provides NFC reading functionality through very simple interface. In order to successfully execute Passive Authentication, you need to provide masterList.pem containing Country Signing Certificate Authority certificate to NFCPassportReader constructor:

  • public init(masterListURL: URL? = nil) - Initialize class with URL to your own masterList.pem file, default file is used if you omit this parameter.

  • public func readPassport(mrzKey: String, result: @escaping ReadPassportResult) → Void - Read passport using MRZ Key.

  • public func readPassport(passportNumber: String, dateOfBirth: Date, dateOfExpiry: Date, result: @escaping ReadPassportResult) → Void - Read passport using Passport Number, Date of Birth and Date of Expiry.


This class contains MRZ Key generation method, date formatting method and method for computing checksum digits in MRZ Key.


This struct holds the data from successful passport reading.


1.2.0 - 2021-03-04


  • DotNfcLocalization class to enable localization of alert messages

1.1.1 - 2020-10-23


  • removed force unwraps and added better error handling

1.1.0 - 2020-07-30


  • Released as a new component dot-nfc

1.0.3 - 2020-03-31


  • Renamed class NFCReader to NFCPassportReader

1.0.2 - 2020-03-31



1.0.1 - 2020-03-12


  • OpenSSL dependancy as an external pod dependancy innovatrics-openssl

1.0.0 - 2020-03-02


  • faceImage and signatureImage to Passport struct