iOS SDK for reading and verifying electronic Machine Readable Travel Documents (eMRTD) locally on-device.
┏━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ ┃
┃ KinegramEmrtd SDK ┃
┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━┛
▲
│ NFC
▼
┌──────────────┐
│ │
│ PASSPORT │
│ │
│ ID CARD │
│ │
│ │
│ (eMRTD) │
│ │
└──────────────┘
The KINEGRAM eMRTD SDK reads and verifies electronic passports and ID cards in accordance with ICAO Doc 9303. All processing happens locally on the device - no server connection required.
Add the following to your Package.swift:
dependencies: [
.package(url: "https://github.com/OVD-Kinegram-AG/emrtd-sdk-ios", from: "2.13.2")
]Or in Xcode:
File -> Packages -> Add Package Dependency... and
enter:
https://github.com/OVD-Kinegram-AG/emrtd-sdk-ios
Add the following to your Podfile:
pod 'KinegramEmrtd', '~> 2.13.2'Then run pod install.
Note: CocoaPods support is provided for compatibility with existing projects. We recommend Swift Package Manager as CocoaPods is only in maintenance mode since September 2024 (official announcement).
import KinegramEmrtd
// Initialize EmrtdReader
let emrtdReader = EmrtdReader()
// Load Master List (CSCA certificates for Passive Authentication)
let masterListURL = Bundle.main.url(forResource: "masterlist", withExtension: "ml")!
try emrtdReader.readMasterlist(from: masterListURL)
// Read and verify passport
let mrzKey = MRZKey(
documentNumber: "123456789",
birthDateyyMMdd: "970101",
expiryDateyyMMdd: "251212"
)
do {
let result = try await emrtdReader.readAndVerify(accessKey: mrzKey)
// Access MRZ info
if let dg1 = result.dg1File {
print("Document Number: \(dg1.documentNumber)")
print("Name: \(dg1.primaryIdentifier) \(dg1.secondaryIdentifier)")
}
// Access face photo
if let faceInfo = result.dg2File?.faceInfos?.first {
let faceImage: UIImage? = faceInfo.uiImage
}
// Check verification results
print("Passive Authentication: \(result.passiveAuthenticationResult)")
print("Active Authentication: \(result.activeAuthenticationResult)")
print("Chip Authentication: \(result.chipAuthenticationResult)")
} catch {
print("Error reading passport: \(error)")
}Some identity documents require PACE polling to be detected (requires iOS 16+):
let canKey = CANKey(can: "123456")
do {
let result = try await emrtdReader.readAndVerify(
accessKey: canKey,
usePACEPolling: true
)
} catch EmrtdReaderError.PACEPollingNotAvailable {
print("PACE polling requires iOS 16 or later")
} catch {
print("Error: \(error)")
}Important: PACE polling cannot detect standard passports - use it only when the document requires it.
Full API documentation is available here
Check out the Example directory for a complete SwiftUI app demonstrating: - MRZ input and validation - NFC passport reading with progress - Verification result display (PA, AA, CA)
do {
let result = try await emrtdReader.readAndVerify(accessKey: mrzKey)
} catch EmrtdReaderError.accessControlFailed {
print("Wrong MRZ data - check document number, birth date, and expiry date")
} catch EmrtdReaderError.PACEPollingNotAvailable {
print("PACE polling requires iOS 16+")
} catch EmrtdReaderError.nfcNotAvailable(let reason) {
print("NFC not available: \(reason)")
} catch {
print("Error: \(error)")
}Enable Near Field Communication Tag Reading in the target Signing & Capabilities.
The *.entitlements file needs:
<dict>
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
<string>PACE</string>
<string>TAG</string>
</array>
</dict>Add the AID list and NFC usage description:
<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>