Kinegram eMRTD SDK iOS

This repository builds and packages two SDKs:

Important notes: - Core and Connector are separate products — do not embed both in the same app. - The Connector is an all‑in‑one build (Core + Connector sources compiled into a single module) but is distributed as a binary‑only package in the separate emrtd-connector-sdk-ios repository (in OVDK’s GitHub). - JPEG2000 (JP2): Core optionally includes OpenJPEG (controlled via -DWITH_OPENJPEG). The Connector does not include JP2 decoding.

Example App

The Xcode Project KinegramEmrtdExample.xcodeproj contains a minimal fully functional demo app, that shows the usage of the SDK. Remember to set your Team in the Signing & Capabilities settings for the Target KinegramEmrtdExample in this project.

Requirements

Running

Set your Team in the Signing & Capabilities settings for all Targets in this project.

Select the scheme ExampleApp and click Run.

Include the Kinegram eMRTD SDK in your app

There are different ways to add KinegramEmrtd.xcframework to your project:

Direct Installation in Xcode

Put the xcframework files into your target’s dependencies. (Project settings –> General –> Frameworks, Libraries, and Embedded Content)

Via SPM (Swift Package Manager)

In your Xcode project, go to File -> Packages -> Add Package Dependency... and enter the URL of this repository or the path to the local folder.

Via Cocoapods (1.9+ required)

There is a prepared KinegramEmrtd.podspec.

If you already use Cocoapods for dependency management, you can simply add the frameworks with one statement in your Podfile:

platform :ios, '13.0'

target 'emrtd-sdk-sample' do
    use_frameworks!

    # local Pod
    pod 'KinegramEmrtd', :path => 'SDK/'

    # ... could be also managed your own git
    #pod 'KinegramEmrtd', :git => 'https://git.yourdomain.com/.git'
end

Then, run pod install command to integrate the SDK into your project.

Additional project Configuration steps

1. Info.plist (AID & NFCReaderUsageDescription)

The AID is a way of uniquely identifying an application on a ISO 7816 tag. eMRTDS use the AID A0000002471001. Your Info.plist entry should look like this:

    <key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
    <array>
        <string>A0000002471001</string>
        <string>A0000002472001</string>
    </array>
    <key>NFCReaderUsageDescription</key>
    <string>This app uses NFC to verify passports</string>

2. Entitlement (Near Field Communication Tag Reading)

This new entitlement is added automatically by Xcode when enabling the Near Field Communication Tag Reading capability in the target Signing & Capabilities.

After enabling the capability the *.entitelments file needs to contain the TAG format:

...
<dict>
    <key>com.apple.developer.nfc.readersession.formats</key>
    <array>
        <string>PACE</string> // Needed for PACE polling support (some ID cards)
        <string>TAG</string>  // Application specific tag, including ISO 7816 Tags
    </array>
</dict>
...

Usage and API description

View the Core DocC documentation (GitLab Pages) or open the .doccarchive locally in Xcode. For the Connector, HTML docs are published via GitHub Pages in the distribution repository.

You can access the documentation from within Xcode by either hitting Shift + Cmd + 0 or through Window -> Developer Documentation.

Quick Example

import KinegramEmrtd

// Initialize EmrtdReader
let emrtdReader = EmrtdReader()

// Load Master List
let masterListURL = Bundle.main.url(forResource: "masterlist", withExtension: "ml")!
try emrtdReader.readMasterlist(from: masterListURL)

// Read and verify passport using async/await
let mrzKey = MRZKey(documentNumber: "123456789", birthDateyyMMdd: "970101", expiryDateyyMMdd: "211212")
do {
    let emrtdResult = try await emrtdReader.readAndVerify(accessKey: mrzKey)

    // Access MRZ info
    if let dg1File = emrtdResult.dg1File {
        print("Document Number: \(dg1File.documentNumber)")
    }

    // Access face photo
    if let faceInfo = emrtdResult.dg2File?.faceInfos?.first {
        let faceImage: UIImage? = faceInfo.uiImage
    }

    // Check verification results
    print("Passive Authentication: \(emrtdResult.passiveAuthenticationResult)")
    print("Active Authentication: \(emrtdResult.activeAuthenticationResult)")
    print("Chip Authentication: \(emrtdResult.chipAuthenticationResult)")
} catch {
    // Handle EmrtdReaderError
    print("Error reading passport: \(error)")
}

Reading PACE-enabled Documents

Some identity documents require PACE (Password Authenticated Connection Establishment) polling to be detected. This includes:

To read these documents, use the usePACEPolling parameter (requires iOS 16+):

// Enable PACE polling for French ID cards and other PACE-enabled documents
let canKey = CANKey(can: "123456")
do {
    let emrtdResult = try await emrtdReader.readAndVerify(accessKey: canKey, usePACEPolling: true)
    // Process result...
} catch EmrtdReaderError.PACEPollingNotAvailable {
    print("PACE polling requires iOS 16 or later")
} catch {
    print("Error reading document: \(error)")
}

Important Notes: - PACE polling is only available on iOS 16 and later - PACE polling cannot detect standard passports - use it only when you know the document requires it - The SDK will throw a PACEPollingNotAvailable error if you try to use PACE polling on iOS 15 or earlier

Changelog

Changelog

Credits