Merge pull request #28 from zk-passport/dev

Dev
This commit is contained in:
turboblitz
2023-12-11 16:24:52 -05:00
committed by GitHub
219 changed files with 603 additions and 96476 deletions

View File

@@ -22,7 +22,7 @@ As a first application, users who can prove they indeed hold a valid passport ca
- ✅ Basic passport verifier circuit
- 🚧 Optimization
- Selective disclosure
- 🚧 Selective disclosure
- ✅ Basic react native frontend
- ✅ Passport verification pipeline, android
- 🚧 Passport verification pipeline, iOS

View File

@@ -38,7 +38,7 @@ import { config } from "@gluestack-ui/config" // Optional if you want to use def
// @ts-ignore
import PassportReader from 'react-native-passport-reader';
import {checkInputs, getFirstName} from './utils/checks';
import {getFirstName, formatDuration, formatProof} from './utils/utils';
import {
DEFAULT_PNUMBER,
DEFAULT_DOB,
@@ -46,9 +46,17 @@ import {
DEFAULT_ADDRESS,
LOCAL_IP,
} from '@env';
import {DataHash, PassportData} from './types/passportData';
import {arraysAreEqual, bytesToBigDecimal, dataHashesObjToArray, formatAndConcatenateDataHashes, formatDuration, formatMrz, formatProof, splitToWords} from './utils/utils';
import {hash, toUnsignedByte} from './utils/computeEContent';
import {DataHash, PassportData} from '../common/src/utils/types';
import {
hash,
toUnsignedByte,
checkInputs,
bytesToBigDecimal,
dataHashesObjToArray,
formatAndConcatenateDataHashes,
formatMrz,
splitToWords
} from '../common/src/utils/utils';
console.log('DEFAULT_PNUMBER', DEFAULT_PNUMBER);
console.log('LOCAL_IP', LOCAL_IP);

View File

@@ -1,4 +1,4 @@
# Embassy App
# Proof of Passport App
Only Android right now, under heavy development

View File

@@ -37,14 +37,14 @@ dependencies {
implementation 'com.google.android.material:material:1.7.0'
implementation 'androidx.core:core-ktx:1.9.0'
implementation 'com.wdullaer:materialdatetimepicker:3.5.2'
implementation 'org.jmrtd:jmrtd:0.7.18'
implementation 'org.jmrtd:jmrtd:0.7.18' // getting different errors whether it's 18 or 40 // 23 <== this works
// implementation files('../../../../../jmrtd-0.7.18-sources/target/jmrtd-0.7.18.jar')
// implementation files('../../app/libs/jmrtd-0.7.18.jar')
implementation 'net.sf.scuba:scuba-sc-android:0.0.18'
implementation 'com.madgag.spongycastle:prov:1.54.0.0'
implementation 'com.gemalto.jp2:jp2-android:1.0.3'
implementation 'com.github.mhshams:jnbis:1.1.0'
implementation 'org.bouncycastle:bcpkix-jdk15on:1.65' // do not update
// implementation 'org.bouncycastle:bcpkix-jdk15on:1.65' // do not update
implementation 'commons-io:commons-io:2.8.0'
implementation 'com.squareup.okhttp3:okhttp:4.9.0'
implementation 'com.android.support:appcompat-v7:25.1.0'
@@ -63,4 +63,4 @@ cargo {
targets = ["arm64", "darwin-aarch64"] // Those work
apiLevel = 29
profile = 'release'
}
}

View File

@@ -254,8 +254,11 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
override fun doInBackground(vararg params: Void?): Exception? {
try {
isoDep.timeout = 10000
Log.e("MY_LOGS", "This should obvsly log")
val cardService = CardService.getInstance(isoDep)
Log.e("MY_LOGS", "cardService gotten")
cardService.open()
Log.e("MY_LOGS", "cardService opened")
val service = PassportService(
cardService,
PassportService.NORMAL_MAX_TRANCEIVE_LENGTH,
@@ -263,31 +266,42 @@ class RNPassportReaderModule(private val reactContext: ReactApplicationContext)
false,
false,
)
Log.e("MY_LOGS", "service gotten")
service.open()
Log.e("MY_LOGS", "service opened")
var paceSucceeded = false
try {
Log.e("MY_LOGS", "trying to get cardAccessFile...")
val cardAccessFile = CardAccessFile(service.getInputStream(PassportService.EF_CARD_ACCESS))
Log.e("MY_LOGS", "cardAccessFile: ${cardAccessFile}")
val securityInfoCollection = cardAccessFile.securityInfos
for (securityInfo: SecurityInfo in securityInfoCollection) {
if (securityInfo is PACEInfo) {
Log.e("MY_LOGS", "trying PACE...")
service.doPACE(
bacKey,
securityInfo.objectIdentifier,
PACEInfo.toParameterSpec(securityInfo.parameterId),
null,
)
Log.e("MY_LOGS", "PACE succeeded")
paceSucceeded = true
}
}
} catch (e: Exception) {
Log.w(TAG, e)
Log.w("MY_LOGS", e)
}
Log.e("MY_LOGS", "Sending select applet command with paceSucceeded: ${paceSucceeded}") // this is false so PACE doesn't succeed
service.sendSelectApplet(paceSucceeded)
if (!paceSucceeded) {
try {
Log.e("MY_LOGS", "trying to get EF_COM...")
service.getInputStream(PassportService.EF_COM).read()
} catch (e: Exception) {
service.doBAC(bacKey)
Log.e("MY_LOGS", "doing BAC")
service.doBAC(bacKey) // <======================== error happens here
Log.e("MY_LOGS", "BAC done")
}
}

View File

@@ -9,4 +9,3 @@
# For example, to use nvm with brew, add the following line
# . "$(brew --prefix nvm)/nvm.sh" --no-use
export NODE_BINARY=$(command -v node)
export BREW_FIX=$(command -v brew)

View File

@@ -1,695 +0,0 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 51;
objects = {
/* Begin PBXBuildFile section */
28BAEE044BE68A5986B97866 /* Pods_NFCPassportReaderApp.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A7BD003B33886ED0F3F03325 /* Pods_NFCPassportReaderApp.framework */; };
8C4EEF9CDD6DAFEF26F8909A /* Pods_NFCPassportReaderAppTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA39DA603B1A7EBD8FC38112 /* Pods_NFCPassportReaderAppTests.framework */; };
A1298C9F25D53A5C00F5713E /* ViewExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1298C9E25D53A5C00F5713E /* ViewExt.swift */; };
A1614B9225D5856600191749 /* ExportPassportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1614B9125D5856600191749 /* ExportPassportView.swift */; };
A16EB23122A9E9E10008F53F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A16EB23022A9E9E10008F53F /* AppDelegate.swift */; };
A16EB23322A9E9E10008F53F /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A16EB23222A9E9E10008F53F /* SceneDelegate.swift */; };
A16EB23A22A9E9E20008F53F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A16EB23922A9E9E20008F53F /* Assets.xcassets */; };
A16EB23D22A9E9E20008F53F /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = A16EB23B22A9E9E20008F53F /* LaunchScreen.storyboard */; };
A17134BE22C8EF7200C457C3 /* MainView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A17134BD22C8EF7100C457C3 /* MainView.swift */; };
A17134C022C8F0A600C457C3 /* PassportUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = A17134BF22C8F0A600C457C3 /* PassportUtils.swift */; };
A17375F525F78B0D005995DA /* PACETests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A17375F425F78B0C005995DA /* PACETests.swift */; };
A1769DF725D3E318006002D1 /* SettingsStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1769DF625D3E318006002D1 /* SettingsStore.swift */; };
A1816E9C22C9059F00F546A0 /* PassportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1816E9B22C9059F00F546A0 /* PassportView.swift */; };
A18248C22369D17300581384 /* DetailsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A18248C12369D17300581384 /* DetailsView.swift */; };
A182DE6125DD6F1300341204 /* StoredPassportView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A182DE6025DD6F1300341204 /* StoredPassportView.swift */; };
A182DE6325DD730D00341204 /* FileManagerExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = A182DE6225DD730D00341204 /* FileManagerExt.swift */; };
A182DE6825DD7EA600341204 /* MRZScannerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = A182DE6725DD7EA600341204 /* MRZScannerViewController.swift */; };
A1A13B9525B8A29E0026074C /* UIApplicationExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1A13B9425B8A29E0026074C /* UIApplicationExt.swift */; };
A1A4C0F725B5E4D70070908B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A1A4C0F625B5E4D70070908B /* Foundation.framework */; };
A1C234C225DD19DE003FFD79 /* PassportSummaryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1C234C125DD19DE003FFD79 /* PassportSummaryView.swift */; };
A1CE83AC22C91D1300E3EACF /* StringExt.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1CE83AB22C91D1300E3EACF /* StringExt.swift */; };
A1DD3F3F22C535F10067255C /* masterList.pem in Resources */ = {isa = PBXBuildFile; fileRef = A1DD3F3E22C535F00067255C /* masterList.pem */; };
A1EBC5242370BAB2004DD19E /* DataGroupParsingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1EBC5212370BAB2004DD19E /* DataGroupParsingTests.swift */; };
A1EBC5252370BAB2004DD19E /* NFCPassportReaderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1EBC5222370BAB2004DD19E /* NFCPassportReaderTests.swift */; };
A1FDC52E25D3F15D00D22FF4 /* SettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FDC52D25D3F15D00D22FF4 /* SettingsView.swift */; };
A1FDC53225D3F19E00D22FF4 /* ViewModifiers.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FDC53125D3F19E00D22FF4 /* ViewModifiers.swift */; };
A1FDC53425D3F1DE00D22FF4 /* CheckBoxView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FDC53325D3F1DE00D22FF4 /* CheckBoxView.swift */; };
A1FDC53625D43AB400D22FF4 /* MRZEntryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = A1FDC53525D43AB400D22FF4 /* MRZEntryView.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
A1EBC5122370B88D004DD19E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = A16EB22522A9E9E10008F53F /* Project object */;
proxyType = 1;
remoteGlobalIDString = A16EB22C22A9E9E10008F53F;
remoteInfo = NFCPassportReaderApp;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
29684A8780D423313153D8B6 /* Pods-NFCPassportReaderAppTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NFCPassportReaderAppTests.release.xcconfig"; path = "Target Support Files/Pods-NFCPassportReaderAppTests/Pods-NFCPassportReaderAppTests.release.xcconfig"; sourceTree = "<group>"; };
3B684038F7C81C32BA310074 /* Pods-NFCPassportReaderAppTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NFCPassportReaderAppTests.debug.xcconfig"; path = "Target Support Files/Pods-NFCPassportReaderAppTests/Pods-NFCPassportReaderAppTests.debug.xcconfig"; sourceTree = "<group>"; };
574315DEF74ED0B9CC6A8DC7 /* Pods-NFCPassportReaderApp.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NFCPassportReaderApp.debug.xcconfig"; path = "Target Support Files/Pods-NFCPassportReaderApp/Pods-NFCPassportReaderApp.debug.xcconfig"; sourceTree = "<group>"; };
A1095E982588FBB100D2A46A /* CHANGELOG */ = {isa = PBXFileReference; lastKnownFileType = text; name = CHANGELOG; path = ../../../CHANGELOG; sourceTree = "<group>"; };
A1095E9B2589032D00D2A46A /* readme.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; name = readme.md; path = ../../readme.md; sourceTree = "<group>"; };
A1298C9E25D53A5C00F5713E /* ViewExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewExt.swift; sourceTree = "<group>"; };
A1614B9125D5856600191749 /* ExportPassportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExportPassportView.swift; sourceTree = "<group>"; };
A16EB22D22A9E9E10008F53F /* NFCPassportReaderApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NFCPassportReaderApp.app; sourceTree = BUILT_PRODUCTS_DIR; };
A16EB23022A9E9E10008F53F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
A16EB23222A9E9E10008F53F /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
A16EB23922A9E9E20008F53F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
A16EB23C22A9E9E20008F53F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
A16EB23E22A9E9E20008F53F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A16EB24422A9EA000008F53F /* NFCPassportReader.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = NFCPassportReader.entitlements; sourceTree = "<group>"; };
A17134BD22C8EF7100C457C3 /* MainView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainView.swift; sourceTree = "<group>"; };
A17134BF22C8F0A600C457C3 /* PassportUtils.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PassportUtils.swift; sourceTree = "<group>"; };
A17375F425F78B0C005995DA /* PACETests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PACETests.swift; sourceTree = "<group>"; };
A1769DF625D3E318006002D1 /* SettingsStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsStore.swift; sourceTree = "<group>"; };
A1816E9B22C9059F00F546A0 /* PassportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassportView.swift; sourceTree = "<group>"; };
A18248C12369D17300581384 /* DetailsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DetailsView.swift; sourceTree = "<group>"; };
A182DE6025DD6F1300341204 /* StoredPassportView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StoredPassportView.swift; sourceTree = "<group>"; };
A182DE6225DD730D00341204 /* FileManagerExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FileManagerExt.swift; sourceTree = "<group>"; };
A182DE6725DD7EA600341204 /* MRZScannerViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MRZScannerViewController.swift; sourceTree = "<group>"; };
A1A13B9425B8A29E0026074C /* UIApplicationExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIApplicationExt.swift; sourceTree = "<group>"; };
A1A4C0F625B5E4D70070908B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
A1C234C125DD19DE003FFD79 /* PassportSummaryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PassportSummaryView.swift; sourceTree = "<group>"; };
A1CE83AB22C91D1300E3EACF /* StringExt.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StringExt.swift; sourceTree = "<group>"; };
A1DD3F3E22C535F00067255C /* masterList.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = masterList.pem; sourceTree = "<group>"; };
A1EBC50D2370B88D004DD19E /* NFCPassportReaderAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NFCPassportReaderAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
A1EBC5112370B88D004DD19E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
A1EBC5212370BAB2004DD19E /* DataGroupParsingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataGroupParsingTests.swift; sourceTree = "<group>"; };
A1EBC5222370BAB2004DD19E /* NFCPassportReaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NFCPassportReaderTests.swift; sourceTree = "<group>"; };
A1FDC52D25D3F15D00D22FF4 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = "<group>"; };
A1FDC53125D3F19E00D22FF4 /* ViewModifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModifiers.swift; sourceTree = "<group>"; };
A1FDC53325D3F1DE00D22FF4 /* CheckBoxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBoxView.swift; sourceTree = "<group>"; };
A1FDC53525D43AB400D22FF4 /* MRZEntryView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MRZEntryView.swift; sourceTree = "<group>"; };
A7BD003B33886ED0F3F03325 /* Pods_NFCPassportReaderApp.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NFCPassportReaderApp.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B239DD4BD3AA9ECF4F595D22 /* Pods-NFCPassportReaderApp.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NFCPassportReaderApp.release.xcconfig"; path = "Target Support Files/Pods-NFCPassportReaderApp/Pods-NFCPassportReaderApp.release.xcconfig"; sourceTree = "<group>"; };
DA39DA603B1A7EBD8FC38112 /* Pods_NFCPassportReaderAppTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NFCPassportReaderAppTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
A16EB22A22A9E9E10008F53F /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
A1A4C0F725B5E4D70070908B /* Foundation.framework in Frameworks */,
28BAEE044BE68A5986B97866 /* Pods_NFCPassportReaderApp.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1EBC50A2370B88D004DD19E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8C4EEF9CDD6DAFEF26F8909A /* Pods_NFCPassportReaderAppTests.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
A1298C9B25D539CD00F5713E /* HelperViews */ = {
isa = PBXGroup;
children = (
A1FDC53325D3F1DE00D22FF4 /* CheckBoxView.swift */,
A1298C9E25D53A5C00F5713E /* ViewExt.swift */,
A1FDC53125D3F19E00D22FF4 /* ViewModifiers.swift */,
);
path = HelperViews;
sourceTree = "<group>";
};
A16EB22422A9E9E10008F53F = {
isa = PBXGroup;
children = (
A16EB22F22A9E9E10008F53F /* NFCPassportReaderApp */,
A1EBC50E2370B88D004DD19E /* NFCPassportReaderAppTests */,
A16EB22E22A9E9E10008F53F /* Products */,
EE354654AF07CDA5F9366735 /* Pods */,
A1A4C0E325B5D3370070908B /* Frameworks */,
);
sourceTree = "<group>";
};
A16EB22E22A9E9E10008F53F /* Products */ = {
isa = PBXGroup;
children = (
A16EB22D22A9E9E10008F53F /* NFCPassportReaderApp.app */,
A1EBC50D2370B88D004DD19E /* NFCPassportReaderAppTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
A16EB22F22A9E9E10008F53F /* NFCPassportReaderApp */ = {
isa = PBXGroup;
children = (
A16EB24422A9EA000008F53F /* NFCPassportReader.entitlements */,
A1CE83AF22C91DB600E3EACF /* Model */,
A182DE6425DD731900341204 /* Extensions */,
A1CE83B022C91DF100E3EACF /* Views */,
A16EB23022A9E9E10008F53F /* AppDelegate.swift */,
A16EB23222A9E9E10008F53F /* SceneDelegate.swift */,
A16EB23922A9E9E20008F53F /* Assets.xcassets */,
A16EB23B22A9E9E20008F53F /* LaunchScreen.storyboard */,
A16EB23E22A9E9E20008F53F /* Info.plist */,
A1DD3F3E22C535F00067255C /* masterList.pem */,
A1095E982588FBB100D2A46A /* CHANGELOG */,
A1095E9B2589032D00D2A46A /* readme.md */,
);
path = NFCPassportReaderApp;
sourceTree = "<group>";
};
A182DE6425DD731900341204 /* Extensions */ = {
isa = PBXGroup;
children = (
A1CE83AB22C91D1300E3EACF /* StringExt.swift */,
A182DE6225DD730D00341204 /* FileManagerExt.swift */,
A1A13B9425B8A29E0026074C /* UIApplicationExt.swift */,
);
path = Extensions;
sourceTree = "<group>";
};
A1A4C0E325B5D3370070908B /* Frameworks */ = {
isa = PBXGroup;
children = (
A1A4C0F625B5E4D70070908B /* Foundation.framework */,
A7BD003B33886ED0F3F03325 /* Pods_NFCPassportReaderApp.framework */,
DA39DA603B1A7EBD8FC38112 /* Pods_NFCPassportReaderAppTests.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
A1CE83AF22C91DB600E3EACF /* Model */ = {
isa = PBXGroup;
children = (
A17134BF22C8F0A600C457C3 /* PassportUtils.swift */,
A1769DF625D3E318006002D1 /* SettingsStore.swift */,
);
path = Model;
sourceTree = "<group>";
};
A1CE83B022C91DF100E3EACF /* Views */ = {
isa = PBXGroup;
children = (
A1298C9B25D539CD00F5713E /* HelperViews */,
A17134BD22C8EF7100C457C3 /* MainView.swift */,
A1FDC53525D43AB400D22FF4 /* MRZEntryView.swift */,
A1FDC52D25D3F15D00D22FF4 /* SettingsView.swift */,
A1816E9B22C9059F00F546A0 /* PassportView.swift */,
A1C234C125DD19DE003FFD79 /* PassportSummaryView.swift */,
A18248C12369D17300581384 /* DetailsView.swift */,
A182DE6025DD6F1300341204 /* StoredPassportView.swift */,
A1614B9125D5856600191749 /* ExportPassportView.swift */,
A182DE6725DD7EA600341204 /* MRZScannerViewController.swift */,
);
path = Views;
sourceTree = "<group>";
};
A1EBC50E2370B88D004DD19E /* NFCPassportReaderAppTests */ = {
isa = PBXGroup;
children = (
A1EBC5212370BAB2004DD19E /* DataGroupParsingTests.swift */,
A1EBC5222370BAB2004DD19E /* NFCPassportReaderTests.swift */,
A1EBC5112370B88D004DD19E /* Info.plist */,
A17375F425F78B0C005995DA /* PACETests.swift */,
);
path = NFCPassportReaderAppTests;
sourceTree = "<group>";
};
EE354654AF07CDA5F9366735 /* Pods */ = {
isa = PBXGroup;
children = (
574315DEF74ED0B9CC6A8DC7 /* Pods-NFCPassportReaderApp.debug.xcconfig */,
B239DD4BD3AA9ECF4F595D22 /* Pods-NFCPassportReaderApp.release.xcconfig */,
3B684038F7C81C32BA310074 /* Pods-NFCPassportReaderAppTests.debug.xcconfig */,
29684A8780D423313153D8B6 /* Pods-NFCPassportReaderAppTests.release.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
A16EB22C22A9E9E10008F53F /* NFCPassportReaderApp */ = {
isa = PBXNativeTarget;
buildConfigurationList = A16EB24122A9E9E20008F53F /* Build configuration list for PBXNativeTarget "NFCPassportReaderApp" */;
buildPhases = (
441F58E6FEE1B28C771C6B72 /* [CP] Check Pods Manifest.lock */,
A16EB22922A9E9E10008F53F /* Sources */,
A16EB22A22A9E9E10008F53F /* Frameworks */,
A16EB22B22A9E9E10008F53F /* Resources */,
4E62328E60F074D699104549 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
dependencies = (
);
name = NFCPassportReaderApp;
productName = NFCTest;
productReference = A16EB22D22A9E9E10008F53F /* NFCPassportReaderApp.app */;
productType = "com.apple.product-type.application";
};
A1EBC50C2370B88D004DD19E /* NFCPassportReaderAppTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = A1EBC5162370B88D004DD19E /* Build configuration list for PBXNativeTarget "NFCPassportReaderAppTests" */;
buildPhases = (
11A5FABC15C673E24DA3F0C2 /* [CP] Check Pods Manifest.lock */,
A1EBC5092370B88D004DD19E /* Sources */,
A1EBC50A2370B88D004DD19E /* Frameworks */,
A1EBC50B2370B88D004DD19E /* Resources */,
);
buildRules = (
);
dependencies = (
A1EBC5132370B88D004DD19E /* PBXTargetDependency */,
);
name = NFCPassportReaderAppTests;
productName = NFCPassportReaderAppTests;
productReference = A1EBC50D2370B88D004DD19E /* NFCPassportReaderAppTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
A16EB22522A9E9E10008F53F /* Project object */ = {
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 1120;
LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "Andy Qua";
TargetAttributes = {
A16EB22C22A9E9E10008F53F = {
CreatedOnToolsVersion = 11.0;
LastSwiftMigration = 1100;
};
A1EBC50C2370B88D004DD19E = {
CreatedOnToolsVersion = 11.2;
TestTargetID = A16EB22C22A9E9E10008F53F;
};
};
};
buildConfigurationList = A16EB22822A9E9E10008F53F /* Build configuration list for PBXProject "NFCPassportReaderApp" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = A16EB22422A9E9E10008F53F;
productRefGroup = A16EB22E22A9E9E10008F53F /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
A16EB22C22A9E9E10008F53F /* NFCPassportReaderApp */,
A1EBC50C2370B88D004DD19E /* NFCPassportReaderAppTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
A16EB22B22A9E9E10008F53F /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A16EB23D22A9E9E20008F53F /* LaunchScreen.storyboard in Resources */,
A1DD3F3F22C535F10067255C /* masterList.pem in Resources */,
A16EB23A22A9E9E20008F53F /* Assets.xcassets in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1EBC50B2370B88D004DD19E /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
11A5FABC15C673E24DA3F0C2 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-NFCPassportReaderAppTests-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
441F58E6FEE1B28C771C6B72 /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-NFCPassportReaderApp-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
4E62328E60F074D699104549 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-NFCPassportReaderApp/Pods-NFCPassportReaderApp-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-NFCPassportReaderApp/Pods-NFCPassportReaderApp-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NFCPassportReaderApp/Pods-NFCPassportReaderApp-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
A16EB22922A9E9E10008F53F /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A182DE6825DD7EA600341204 /* MRZScannerViewController.swift in Sources */,
A1CE83AC22C91D1300E3EACF /* StringExt.swift in Sources */,
A1FDC53625D43AB400D22FF4 /* MRZEntryView.swift in Sources */,
A17134BE22C8EF7200C457C3 /* MainView.swift in Sources */,
A16EB23122A9E9E10008F53F /* AppDelegate.swift in Sources */,
A1816E9C22C9059F00F546A0 /* PassportView.swift in Sources */,
A1769DF725D3E318006002D1 /* SettingsStore.swift in Sources */,
A1298C9F25D53A5C00F5713E /* ViewExt.swift in Sources */,
A182DE6325DD730D00341204 /* FileManagerExt.swift in Sources */,
A1FDC52E25D3F15D00D22FF4 /* SettingsView.swift in Sources */,
A182DE6125DD6F1300341204 /* StoredPassportView.swift in Sources */,
A1FDC53225D3F19E00D22FF4 /* ViewModifiers.swift in Sources */,
A1C234C225DD19DE003FFD79 /* PassportSummaryView.swift in Sources */,
A1614B9225D5856600191749 /* ExportPassportView.swift in Sources */,
A18248C22369D17300581384 /* DetailsView.swift in Sources */,
A1FDC53425D3F1DE00D22FF4 /* CheckBoxView.swift in Sources */,
A1A13B9525B8A29E0026074C /* UIApplicationExt.swift in Sources */,
A16EB23322A9E9E10008F53F /* SceneDelegate.swift in Sources */,
A17134C022C8F0A600C457C3 /* PassportUtils.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
A1EBC5092370B88D004DD19E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
A1EBC5252370BAB2004DD19E /* NFCPassportReaderTests.swift in Sources */,
A17375F525F78B0D005995DA /* PACETests.swift in Sources */,
A1EBC5242370BAB2004DD19E /* DataGroupParsingTests.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
A1EBC5132370B88D004DD19E /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = A16EB22C22A9E9E10008F53F /* NFCPassportReaderApp */;
targetProxy = A1EBC5122370B88D004DD19E /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
A16EB23B22A9E9E20008F53F /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
A16EB23C22A9E9E20008F53F /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
A16EB23F22A9E9E20008F53F /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
A16EB24022A9E9E20008F53F /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
VALIDATE_PRODUCT = YES;
};
name = Release;
};
A16EB24222A9E9E20008F53F /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 574315DEF74ED0B9CC6A8DC7 /* Pods-NFCPassportReaderApp.debug.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = NFCPassportReaderApp/NFCPassportReader.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 4.1;
DEVELOPMENT_TEAM = BV8DN58CD3;
INFOPLIST_FILE = NFCPassportReaderApp/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1;
PRODUCT_BUNDLE_IDENTIFIER = com.iag.nfcpassportreader;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Debug;
};
A16EB24322A9E9E20008F53F /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = B239DD4BD3AA9ECF4F595D22 /* Pods-NFCPassportReaderApp.release.xcconfig */;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = NFCPassportReaderApp/NFCPassportReader.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 4.1;
DEVELOPMENT_TEAM = BV8DN58CD3;
INFOPLIST_FILE = NFCPassportReaderApp/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1;
PRODUCT_BUNDLE_IDENTIFIER = com.iag.nfcpassportreader;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
name = Release;
};
A1EBC5142370B88D004DD19E /* Debug */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 3B684038F7C81C32BA310074 /* Pods-NFCPassportReaderAppTests.debug.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = A4ZM73UFF5;
INFOPLIST_FILE = NFCPassportReaderAppTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.2;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.andyqua.NFCPassportReaderAppTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NFCPassportReaderApp.app/NFCPassportReaderApp";
};
name = Debug;
};
A1EBC5152370B88D004DD19E /* Release */ = {
isa = XCBuildConfiguration;
baseConfigurationReference = 29684A8780D423313153D8B6 /* Pods-NFCPassportReaderAppTests.release.xcconfig */;
buildSettings = {
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = A4ZM73UFF5;
INFOPLIST_FILE = NFCPassportReaderAppTests/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 13.2;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.andyqua.NFCPassportReaderAppTests;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/NFCPassportReaderApp.app/NFCPassportReaderApp";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
A16EB22822A9E9E10008F53F /* Build configuration list for PBXProject "NFCPassportReaderApp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A16EB23F22A9E9E20008F53F /* Debug */,
A16EB24022A9E9E20008F53F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A16EB24122A9E9E20008F53F /* Build configuration list for PBXNativeTarget "NFCPassportReaderApp" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A16EB24222A9E9E20008F53F /* Debug */,
A16EB24322A9E9E20008F53F /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
A1EBC5162370B88D004DD19E /* Build configuration list for PBXNativeTarget "NFCPassportReaderAppTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
A1EBC5142370B88D004DD19E /* Debug */,
A1EBC5152370B88D004DD19E /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = A16EB22522A9E9E10008F53F /* Project object */;
}

View File

@@ -1,106 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A16EB22C22A9E9E10008F53F"
BuildableName = "NFCPassportReaderApp.app"
BlueprintName = "NFCPassportReaderApp"
ReferencedContainer = "container:NFCPassportReaderApp.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "NFCPassportReaderTests"
BuildableName = "NFCPassportReaderTests"
BlueprintName = "NFCPassportReaderTests"
ReferencedContainer = "container:..">
</BuildableReference>
</TestableReference>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A1EBC50C2370B88D004DD19E"
BuildableName = "NFCPassportReaderAppTests.xctest"
BlueprintName = "NFCPassportReaderAppTests"
ReferencedContainer = "container:NFCPassportReaderApp.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
disableMainThreadChecker = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A16EB22C22A9E9E10008F53F"
BuildableName = "NFCPassportReaderApp.app"
BlueprintName = "NFCPassportReaderApp"
ReferencedContainer = "container:NFCPassportReaderApp.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
<EnvironmentVariables>
<EnvironmentVariable
key = "OS_ACTIVITY_MODE"
value = "disable"
isEnabled = "YES">
</EnvironmentVariable>
</EnvironmentVariables>
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<BuildableProductRunnable
runnableDebuggingMode = "0">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "A16EB22C22A9E9E10008F53F"
BuildableName = "NFCPassportReaderApp.app"
BlueprintName = "NFCPassportReaderApp"
ReferencedContainer = "container:NFCPassportReaderApp.xcodeproj">
</BuildableReference>
</BuildableProductRunnable>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:NFCPassportReaderApp.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View File

@@ -1,39 +0,0 @@
//
// AppDelegate.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 06/06/2019.
// Copyright © 2019 Andy Qua. All rights reserved.
//
import UIKit
import CoreNFC
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
return true
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
}

View File

@@ -1,158 +0,0 @@
{
"info" : {
"author" : "xcode",
"version" : 1
},
"images" : [
{
"size" : "40x40",
"filename" : "icon-40.png",
"idiom" : "ipad",
"scale" : "1x"
},
{
"size" : "40x40",
"idiom" : "ipad",
"scale" : "2x",
"filename" : "icon-40@2x.png"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x",
"filename" : "icon-60@2x.png"
},
{
"idiom" : "ipad",
"filename" : "icon-72.png",
"size" : "72x72",
"scale" : "1x"
},
{
"scale" : "2x",
"idiom" : "ipad",
"size" : "72x72",
"filename" : "icon-72@2x.png"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x",
"filename" : "icon-76.png"
},
{
"scale" : "2x",
"size" : "76x76",
"idiom" : "ipad",
"filename" : "icon-76@2x.png"
},
{
"idiom" : "ipad",
"size" : "50x50",
"filename" : "icon-small-50.png",
"scale" : "1x"
},
{
"scale" : "2x",
"filename" : "icon-small-50@2x.png",
"size" : "50x50",
"idiom" : "ipad"
},
{
"scale" : "1x",
"filename" : "icon-small.png",
"idiom" : "iphone",
"size" : "29x29"
},
{
"scale" : "2x",
"size" : "29x29",
"idiom" : "iphone",
"filename" : "icon-small@2x.png"
},
{
"filename" : "icon.png",
"idiom" : "iphone",
"size" : "57x57",
"scale" : "1x"
},
{
"scale" : "2x",
"size" : "57x57",
"idiom" : "iphone",
"filename" : "icon@2x.png"
},
{
"filename" : "icon-small@3x.png",
"size" : "29x29",
"idiom" : "iphone",
"scale" : "3x"
},
{
"size" : "40x40",
"scale" : "3x",
"idiom" : "iphone",
"filename" : "icon-40@3x.png"
},
{
"filename" : "icon-60@3x.png",
"scale" : "3x",
"idiom" : "iphone",
"size" : "60x60"
},
{
"size" : "40x40",
"filename" : "icon-40@2x.png",
"idiom" : "iphone",
"scale" : "2x"
},
{
"scale" : "1x",
"idiom" : "ipad",
"size" : "29x29",
"filename" : "icon-small.png"
},
{
"size" : "29x29",
"scale" : "2x",
"filename" : "icon-small@2x.png",
"idiom" : "ipad"
},
{
"idiom" : "ipad",
"filename" : "icon-83.5@2x.png",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"size" : "20x20",
"scale" : "2x",
"filename" : "notification-icon@2x.png",
"idiom" : "iphone"
},
{
"scale" : "3x",
"filename" : "notification-icon@3x.png",
"idiom" : "iphone",
"size" : "20x20"
},
{
"filename" : "notification-icon~ipad.png",
"idiom" : "ipad",
"size" : "20x20",
"scale" : "1x"
},
{
"filename" : "notification-icon~ipad@2x.png",
"size" : "20x20",
"scale" : "2x",
"idiom" : "ipad"
},
{
"filename" : "ios-marketing.png",
"size" : "1024x1024",
"idiom" : "ios-marketing",
"scale" : "1x"
}
]
}

View File

@@ -1,6 +0,0 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@@ -1,21 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "background.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 387 KiB

View File

@@ -1,21 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "head.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 187 KiB

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View File

@@ -1,16 +0,0 @@
//
// FileManagerExt.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 17/02/2021.
// Copyright © 2021 Andy Qua. All rights reserved.
//
import SwiftUI
extension FileManager {
static var cachesFolder : URL {
FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
}
}

View File

@@ -1,40 +0,0 @@
//
// StringExt.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 30/06/2019.
// Copyright © 2019 Andy Qua. All rights reserved.
//
import Foundation
/// Some Utility methods for string - access characters by index
extension String {
subscript(_ i: Int) -> String {
let idx1 = index(startIndex, offsetBy: i)
let idx2 = index(idx1, offsetBy: 1)
return String(self[idx1..<idx2])
}
subscript (bounds: CountableRange<Int>) -> String {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return String(self[start..<end])
}
subscript (bounds: CountableClosedRange<Int>) -> String {
let start = index(startIndex, offsetBy: bounds.lowerBound)
let end = index(startIndex, offsetBy: bounds.upperBound)
return String(self[start...end])
}
subscript (bounds: CountablePartialRangeFrom<Int>) -> String {
let start = index(startIndex, offsetBy: bounds.lowerBound)
return String(self[start...])
}
func strip() -> String {
let trimmed = self.trimmingCharacters(in: .whitespacesAndNewlines)
return trimmed
}
}

View File

@@ -1,21 +0,0 @@
//
// UIApplicationExt.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 20/01/2021.
// Copyright © 2021 Andy Qua. All rights reserved.
//
import UIKit
extension UIApplication {
static var release: String {
return Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as! String? ?? "x.x"
}
static var build: String {
return Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as! String? ?? "x"
}
static var version: String {
return "\(release).\(build)"
}
}

View File

@@ -1,77 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>NFCPassportReaderApp</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>$(MARKETING_VERSION)</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NFCReaderUsageDescription</key>
<string>This app uses NFC to scan passports</string>
<key>NSCameraUsageDescription</key>
<string>This app uses the camera to read passports</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
</dict>
</array>
</dict>
</dict>
<key>UIFileSharingEnabled</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>nfc</string>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>com.apple.developer.nfc.readersession.iso7816.select-identifiers</key>
<array>
<string>A0000002471001</string>
<string>A0000002472001</string>
<string>00000000000000</string>
</array>
</dict>
</plist>

View File

@@ -1,76 +0,0 @@
//
// PassportUtils.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 30/06/2019.
// Copyright © 2019 Andy Qua. All rights reserved.
//
import NFCPassportReader
class PassportUtils {
func getMRZKey(passportNumber: String, dateOfBirth: String, dateOfExpiry: String ) -> String {
// Pad fields if necessary
let pptNr = pad( passportNumber, fieldLength:9)
let dob = pad( dateOfBirth, fieldLength:6)
let exp = pad( dateOfExpiry, fieldLength:6)
// Calculate checksums
let passportNrChksum = calcCheckSum(pptNr)
let dateOfBirthChksum = calcCheckSum(dob)
let expiryDateChksum = calcCheckSum(exp)
let mrzKey = "\(pptNr)\(passportNrChksum)\(dob)\(dateOfBirthChksum)\(exp)\(expiryDateChksum)"
return mrzKey
}
func pad( _ value : String, fieldLength:Int ) -> String {
// Pad out field lengths with < if they are too short
let paddedValue = (value + String(repeating: "<", count: fieldLength)).prefix(fieldLength)
return String(paddedValue)
}
func calcCheckSum( _ checkString : String ) -> Int {
let characterDict = ["0" : "0", "1" : "1", "2" : "2", "3" : "3", "4" : "4", "5" : "5", "6" : "6", "7" : "7", "8" : "8", "9" : "9", "<" : "0", " " : "0", "A" : "10", "B" : "11", "C" : "12", "D" : "13", "E" : "14", "F" : "15", "G" : "16", "H" : "17", "I" : "18", "J" : "19", "K" : "20", "L" : "21", "M" : "22", "N" : "23", "O" : "24", "P" : "25", "Q" : "26", "R" : "27", "S" : "28","T" : "29", "U" : "30", "V" : "31", "W" : "32", "X" : "33", "Y" : "34", "Z" : "35"]
var sum = 0
var m = 0
let multipliers : [Int] = [7, 3, 1]
for c in checkString {
guard let lookup = characterDict["\(c)"],
let number = Int(lookup) else { return 0 }
let product = number * multipliers[m]
sum += product
m = (m+1) % 3
}
return (sum % 10)
}
static func shareLogs() {
do {
let arr = Log.logData
let data = try JSONSerialization.data(withJSONObject: arr, options: .prettyPrinted)
let temporaryURL = URL(fileURLWithPath: NSTemporaryDirectory() + "passportreader.log")
try data.write(to: temporaryURL)
let av = UIActivityViewController(activityItems: [temporaryURL], applicationActivities: nil)
let keyWindow = UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows
.filter({$0.isKeyWindow}).first
keyWindow?.rootViewController?.present(av, animated: true, completion: nil)
} catch {
print( "ERROR - \(error)" )
}
}
}

View File

@@ -1,107 +0,0 @@
//
// SettingsStore.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 10/02/2021.
// Copyright © 2021 Andy Qua. All rights reserved.
//
import SwiftUI
import Combine
import NFCPassportReader
final class SettingsStore: ObservableObject {
private enum Keys {
static let captureLog = "captureLog"
static let logLevel = "logLevel"
static let useNewVerification = "useNewVerification"
static let savePassportOnScan = "savePassportOnScan"
static let passportNumber = "passportNumber"
static let dateOfBirth = "dateOfBirth"
static let dateOfExpiry = "dateOfExpiry"
static let allVals = [captureLog, logLevel, useNewVerification, passportNumber, dateOfBirth, dateOfExpiry]
}
private let cancellable: Cancellable
private let defaults: UserDefaults
let objectWillChange = PassthroughSubject<Void, Never>()
init(defaults: UserDefaults = .standard) {
self.defaults = defaults
defaults.register(defaults: [
Keys.captureLog: true,
Keys.logLevel: 1,
Keys.useNewVerification: true,
Keys.savePassportOnScan: false,
Keys.passportNumber: "",
Keys.dateOfBirth: Date().timeIntervalSince1970,
Keys.dateOfExpiry: Date().timeIntervalSince1970,
])
cancellable = NotificationCenter.default
.publisher(for: UserDefaults.didChangeNotification)
.map { _ in () }
.subscribe(objectWillChange)
}
func reset() {
if let bundleID = Bundle.main.bundleIdentifier {
UserDefaults.standard.removePersistentDomain(forName: bundleID)
}
}
var shouldCaptureLogs: Bool {
set { defaults.set(newValue, forKey: Keys.captureLog) }
get { defaults.bool(forKey: Keys.captureLog) }
}
var logLevel: LogLevel {
get {
return LogLevel(rawValue:defaults.integer(forKey: Keys.logLevel)) ?? .info
}
set {
defaults.set(newValue.rawValue, forKey: Keys.logLevel)
}
}
var useNewVerificationMethod: Bool {
set { defaults.set(newValue, forKey: Keys.useNewVerification) }
get { defaults.bool(forKey: Keys.useNewVerification) }
}
var savePassportOnScan: Bool {
set { defaults.set(newValue, forKey: Keys.savePassportOnScan) }
get { defaults.bool(forKey: Keys.savePassportOnScan) }
}
var passportNumber: String {
set { defaults.set(newValue, forKey: Keys.passportNumber) }
get { defaults.string(forKey: Keys.passportNumber) ?? "" }
}
var dateOfBirth: Date {
set {
defaults.set(newValue.timeIntervalSince1970, forKey: Keys.dateOfBirth)
}
get {
let d = Date(timeIntervalSince1970: defaults.double(forKey: Keys.dateOfBirth))
return d
}
}
var dateOfExpiry: Date {
set {
defaults.set(newValue.timeIntervalSince1970, forKey: Keys.dateOfExpiry) }
get {
let d = Date(timeIntervalSince1970: defaults.double(forKey: Keys.dateOfExpiry))
return d
}
}
@Published var passport : NFCPassportModel?
}

View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.developer.nfc.readersession.formats</key>
<array>
<string>TAG</string>
</array>
</dict>
</plist>

View File

@@ -1,57 +0,0 @@
//
// SceneDelegate.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 06/06/2019.
// Copyright © 2019 Andy Qua. All rights reserved.
//
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
var settings = SettingsStore()
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// Use a UIHostingController as window root view controller
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: MainView().environmentObject(settings))
self.window = window
window.makeKeyAndVisible()
}
}
func sceneDidDisconnect(_ scene: UIScene) {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead).
}
func sceneDidBecomeActive(_ scene: UIScene) {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
func sceneWillResignActive(_ scene: UIScene) {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
func sceneWillEnterForeground(_ scene: UIScene) {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
func sceneDidEnterBackground(_ scene: UIScene) {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
}

View File

@@ -1,197 +0,0 @@
//
// DetailsView.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 30/10/2019.
// Copyright © 2019 Andy Qua. All rights reserved.
//
import SwiftUI
import NFCPassportReader
struct Item : Identifiable {
var id = UUID()
var title : String
var value : String
var textColor : Color {
return value.hasPrefix("FAILED") ? Color.red : Color.primary
}
}
struct DetailsView : View {
private var passport: NFCPassportModel
private var sectionNames = ["Chip information", "Verification information", "Document signing certificate", "Country signing certificate", "Security Info details", "Datagroup Hashes"]
private var sections = [[Item]]()
init( passport : NFCPassportModel ) {
self.passport = passport
sections.append(getChipInfoSection(self.passport))
sections.append(getVerificationDetailsSection(self.passport))
sections.append(getCertificateSigningCertDetails(certItems:self.passport.documentSigningCertificate?.getItemsAsDict()))
sections.append(getCertificateSigningCertDetails(certItems:self.passport.countrySigningCertificate?.getItemsAsDict()))
sections.append(getSecurityInfosSection(self.passport))
sections.append(getDataGroupHashesSection(self.passport))
}
var body: some View {
VStack {
List {
ForEach( 0 ..< self.sectionNames.count ) { i in
if self.sections[i].count > 0 {
SectionGroup(sectionTitle: self.sectionNames[i], items: self.sections[i])
}
}
}
}
}
func getChipInfoSection(_ passport: NFCPassportModel) -> [Item] {
// Build Chip info section
let chipInfo = [Item(title:"LDS Version", value: passport.LDSVersion),
Item(title:"Data groups present", value: passport.dataGroupsPresent.joined(separator: ", ")),
Item(title:"Data groups read", value: passport.dataGroupsAvailable.map { $0.getName()}.joined(separator: ", "))]
return chipInfo
}
func getVerificationDetailsSection(_ passport: NFCPassportModel) -> [Item] {
// Build Verification Info section
var activeAuth : String = "Not supported"
if passport.activeAuthenticationSupported {
activeAuth = passport.activeAuthenticationPassed ? "SUCCESS\nSignature verified" : "FAILED\nCould not verify signature"
}
var chipAuth : String = "Not supported"
if passport.isChipAuthenticationSupported {
switch( passport.chipAuthenticationStatus ) {
case .notDone:
chipAuth = "Supported - Not done"
case .success:
chipAuth = "SUCCESS\nSignature verified"
case .failed:
chipAuth = "FAILED\nCould not verify signature"
}
}
var authType : String = "Authentication not done"
if passport.PACEStatus == .success {
authType = "PACE"
} else if passport.BACStatus == .success {
authType = "BAC"
}
// Do PACE Info
var paceStatus = "Not Supported"
if passport.isPACESupported {
switch( passport.PACEStatus ) {
case .notDone:
paceStatus = "Supported - Not done"
case .success:
paceStatus = "SUCCESS"
case .failed:
paceStatus = "FAILED"
}
}
let verificationDetails : [Item] = [
Item(title: "Access Control", value: authType),
Item(title: "PACE", value: paceStatus),
Item(title: "Chip Authentication", value: chipAuth),
Item(title: "Active Authentication", value: activeAuth),
Item(title: "Document Signing Certificate", value: passport.documentSigningCertificateVerified ? "SUCCESS\nSOD Signature verified" : "FAILED\nCouldn't verify SOD signature"),
Item(title: "Country signing Certificate", value: passport.passportCorrectlySigned ? "SUCCESS\nmatched to country signing certificate" : "FAILED\nCouldn't build trust chain"),
Item(title: "Data group hashes", value: passport.passportDataNotTampered ? "SUCCESS\nAll hashes match" : "FAILED\nCouldn't match hashes" )
]
return verificationDetails
}
func getCertificateSigningCertDetails( certItems : [CertificateItem : String]? ) -> [Item] {
let titles : [String] = ["Serial number", "Signature algorithm", "Public key algorithm", "Certificate fingerprint", "Issuer", "Subject", "Valid from", "Valid to"]
var items = [Item]()
if certItems?.count ?? 0 == 0 {
items.append( Item(title:"Certificate details", value: "NOT FOUND" ) )
} else {
for title in titles {
let ci = CertificateItem(rawValue:title)!
items.append( Item(title:title, value: certItems?[ci] ?? "") )
}
}
return items
}
func getDataGroupHashesSection(_ passport: NFCPassportModel) -> [Item] {
var dgHashes = [Item]()
for id in DataGroupId.allCases {
if let hash = passport.dataGroupHashes[id] {
dgHashes.append( Item(title:hash.id, value:hash.match ? "MATCHED" : "UNMATCHED"))
dgHashes.append( Item(title:"SOD Hash", value: hash.sodHash))
dgHashes.append( Item(title:"Computed Hash", value: hash.computedHash))
}
}
return dgHashes
}
func getSecurityInfosSection( _ passport : NFCPassportModel) -> [Item] {
guard let dg14 = passport.getDataGroup(.DG14) as? DataGroup14 else { return [] }
var items = [Item]()
for secInfo in dg14.securityInfos {
var title : String = ""
var value : String = ""
if let cai = secInfo as? ChipAuthenticationInfo {
title = "ChipAuthenticationInfo"
value = "\(secInfo.getProtocolOIDString())\n\(secInfo.getObjectIdentifier())\nUses Key Id: \(cai.getKeyId())"
} else if let capki = secInfo as? ChipAuthenticationPublicKeyInfo {
title = "ChipAuthenticationPublicKeyInfo"
value = "\(secInfo.getProtocolOIDString())\n\(secInfo.getObjectIdentifier())\nKey Id: \(capki.getKeyId())"
} else if let pacei = secInfo as? PACEInfo {
title = "PACEInfo"
value = "\(pacei.getProtocolOIDString())\n\(pacei.getObjectIdentifier())\nParameter ID: \(pacei.getParameterId() ?? -1)"
} else if let activeAuthInfo = secInfo as? ActiveAuthenticationInfo {
title = "ActiveAuthenticationInfo"
value =
"\(activeAuthInfo.getProtocolOIDString())\n\(activeAuthInfo.getSignatureAlgorithmOIDString() ?? "")"
}
items.append( Item(title:title, value: value))
}
return items
}
}
struct SectionGroup : View {
var sectionTitle : String
var items : [Item]
var body: some View {
Section(header: Text(sectionTitle)) {
ForEach(self.items) { item in
VStack(alignment:.leading, spacing:0) {
Text(item.title)
.font(.headline)
Text(item.value)
.foregroundColor(item.textColor)
.lineLimit(nil)
}
}
}
}
}
struct DetailsView_Previews: PreviewProvider {
static var previews: some View {
let settings = SettingsStore()
let passport = NFCPassportModel()
return DetailsView(passport:passport)
.environmentObject(settings)
.environment( \.colorScheme, .light)
}
}

View File

@@ -1,164 +0,0 @@
//
// ExportPassportView.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 11/02/2021.
// Copyright © 2021 Andy Qua. All rights reserved.
//
import SwiftUI
import NFCPassportReader
struct MultipleSelectionRow: View {
var title: String
var isSelected: Bool
var action: () -> Void
var body: some View {
Button(action: self.action) {
HStack {
Text(self.title)
if self.isSelected {
Spacer()
Image(systemName: "checkmark")
}
}
}
.foregroundColor(.primary)
}
}
struct ExportPassportView: View {
@EnvironmentObject var settings: SettingsStore
@State var items: [DataGroupId] = []
@State var selections: [DataGroupId] = []
@State var isAASupported : Bool = false
@State var includeAA : Bool = false
var body: some View {
Form {
Section(header: Text("Select Passport items to export"), footer:Text("* contains personal information")) {
List {
ForEach(items, id: \.self) { item in
MultipleSelectionRow(title: dgToText(item), isSelected: self.selections.contains(item)) {
if self.selections.contains(item) {
self.selections.removeAll(where: { $0 == item })
}
else {
self.selections.append(item)
}
}
}
}
if isAASupported {
Toggle("Include Active Authentication Challenge/Response?", isOn: $includeAA)
.foregroundColor(.primary)
}
}
Button(action: {
sharePassport()
}, label: {
Text("Export selected passport details")
.font(.title3)
})
.foregroundColor(.primary)
}
.navigationTitle("Export passport")
.onAppear() {
if let passport = settings.passport {
items = [.SOD, .COM]
items.append(contentsOf: DataGroupId.allCases.filter { passport.dataGroupsAvailable.contains($0) } )
// Default select only the DGs that contain no personal info.
selections = [.SOD, .COM, .DG14, .DG15]
isAASupported = passport.activeAuthenticationSupported
if isAASupported {
includeAA = true
}
}
}
}
}
extension ExportPassportView {
func sharePassport() {
do {
let dict = settings.passport!.dumpPassportData( selectedDataGroups:selections,includeActiveAuthenticationData: includeAA)
let data = try JSONSerialization.data(withJSONObject: dict, options: .prettyPrinted)
let temporaryURL = URL(fileURLWithPath: NSTemporaryDirectory() + "passport.json")
try data.write(to: temporaryURL)
let av = UIActivityViewController(activityItems: [temporaryURL], applicationActivities: nil)
let keyWindow = UIApplication.shared.connectedScenes
.filter({$0.activationState == .foregroundActive})
.map({$0 as? UIWindowScene})
.compactMap({$0})
.first?.windows
.filter({$0.isKeyWindow}).first
keyWindow?.rootViewController?.present(av, animated: true, completion: nil)
} catch {
print( "ERROR - \(error)" )
}
}
func dgToText( _ dg : DataGroupId ) -> String {
switch ( dg ) {
case .SOD:
return "SOD - Document Security Object"
case .COM:
return "COM - Header and DG Presence"
case .DG1:
return "DG1* - MRZ Info"
case .DG2:
return "DG2* - Face image"
case .DG3:
return "DG3* - Fingerprints"
case .DG4:
return "DG4* - Iris"
case .DG5:
return "DG5* - Displayed portrait"
case .DG6:
return "DG6 - Reserved"
case .DG7:
return "DG7* - Signature"
case .DG8:
return "DG8* - Data features"
case .DG9:
return "DG9* - Structure features"
case .DG10:
return "DG10* - Substance features"
case .DG11:
return "DG11* - Additional personal info"
case .DG12:
return "DG12* - Additional document info"
case .DG13:
return "DG13* - Optional details"
case .DG14:
return "DG14 - Security options"
case .DG15:
return "DG15 - Active Auth PubKey"
case .DG16:
return "DG16 - Person(s) to notify"
default:
return "Unknown"
}
}
}
struct ExportPassportView_Previews: PreviewProvider {
static var previews: some View {
let settings = SettingsStore()
settings.passport = NFCPassportModel()
return NavigationView {
ExportPassportView()
}
.environmentObject(settings)
}
}

View File

@@ -1,48 +0,0 @@
//
// CheckBoxView.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 10/02/2021.
// Copyright © 2021 Andy Qua. All rights reserved.
//
import SwiftUI
struct CheckBoxButtonStyle: ButtonStyle {
func makeBody(configuration: Self.Configuration) -> some View {
configuration.label
.foregroundColor(.secondary)
}
}
struct CheckBoxView: View {
@Binding var checked: Bool
var text : String
var body: some View {
HStack() {
Button(action: {
withAnimation {
self.checked.toggle()
}
}) {
HStack(alignment: .center, spacing: 10) {
Text(text)
Image(systemName:self.checked ? "checkmark.square.fill" : "square")
}
}
.frame(height: 44, alignment: .center)
.padding(.trailing)
.buttonStyle(CheckBoxButtonStyle())
}
}
}
struct CheckBoxView_Previews: PreviewProvider {
static var previews: some View {
CheckBoxView( checked: .constant(true), text:"Are you on?")
}
}

View File

@@ -1,20 +0,0 @@
//
// ViewExt.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 11/02/2021.
// Copyright © 2021 Andy Qua. All rights reserved.
//
import SwiftUI
import UIKit
extension View {
func hideKeyboard() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
func visibility(hidden: Binding<Bool>) -> some View {
modifier(VisibilityStyle(hidden: hidden))
}
}

View File

@@ -1,41 +0,0 @@
//
// ViewModifiers.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 10/02/2021.
// Copyright © 2021 Andy Qua. All rights reserved.
//
import SwiftUI
struct ClearButton: ViewModifier {
@Binding var text: String
public func body(content: Content) -> some View {
HStack {
content
if !text.isEmpty {
Button(action: { self.text = "" },
label: {
Image(systemName: "delete.left")
.foregroundColor(Color(UIColor.opaqueSeparator))
}
)
}
}
}
}
struct VisibilityStyle: ViewModifier {
@Binding var hidden: Bool
func body(content: Content) -> some View {
Group {
if hidden {
content.hidden()
} else {
content
}
}
}
}

View File

@@ -1,125 +0,0 @@
//
// MRZEntryView.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 10/02/2021.
// Copyright © 2021 Andy Qua. All rights reserved.
//
import SwiftUI
// This will be removed once DatePicker inline works correctly
struct DateView : View {
@Binding var date : Date
var title : String
var body : some View {
VStack {
Text(title)
.font(.largeTitle)
Spacer()
DatePicker("Date of birth", selection:$date, displayedComponents: .date)
.environment(\.timeZone, TimeZone(secondsFromGMT: 0)!)
.datePickerStyle(WheelDatePickerStyle())
.labelsHidden()
Spacer()
}
}
}
// This should be a nice simple inline DatePicker here
// BUT there are bugs when you select dates it changes the date format
// from DD MMM YYYY to DD/MM/YYYY!)
// Will update when/if this gets fixed!
struct MRZEntryView : View {
@EnvironmentObject var settings: SettingsStore
// These will be removed once DatePicker inline works correctly
@State private var editDOB = false
@State private var editDOE = false
@State private var editDateTitle : String = ""
var body : some View {
let passportNrBinding = Binding<String>(get: {
settings.passportNumber
}, set: {
settings.passportNumber = $0.uppercased()
})
VStack {
NavigationLink( destination: DateView(date:$settings.dateOfBirth, title:editDateTitle), isActive: $editDOB) { Text("") }
NavigationLink( destination: DateView(date:$settings.dateOfExpiry, title:editDateTitle), isActive: $editDOE) { Text("") }
TextField("Passport number", text: passportNrBinding)
.textCase(.uppercase)
.modifier(ClearButton(text: passportNrBinding))
.textContentType(.name)
.foregroundColor(Color.primary)
.padding([.leading, .trailing])
.ignoresSafeArea(.keyboard, edges: .all)
Divider()
// Replace with DatePicker once it works correctly
HStack {
VStack {
Text( "Date of birth" )
Button(formatDate(settings.dateOfBirth)) {
editDateTitle = "Select date of birth"
editDOB = true
}
.padding(.horizontal, 15)
.padding(.vertical, 8)
.background(Color.black.opacity(0.07))
.cornerRadius(8)
}
Spacer()
VStack {
Text( "Passport expiry date" )
Button(formatDate(settings.dateOfExpiry)) {
editDateTitle = "Select passport expiry date"
editDOE = true
}
.padding(.horizontal, 15)
.padding(.vertical, 8)
.background(Color.black.opacity(0.07))
.cornerRadius(8)
}
}
.padding([.leading, .trailing])
Divider()
}
.ignoresSafeArea(.keyboard, edges: .bottom)
}
}
// This will be removed once DatePicker inline works correctly
extension MRZEntryView {
func formatDate( _ date : Date ) -> String {
let df = DateFormatter()
df.timeZone = TimeZone.init(secondsFromGMT: 0)
df.dateFormat = "dd MMM yyyy"
let dateStr = df.string(from:date)
return dateStr
}
}
#if DEBUG
struct MRZEntryView_Previews : PreviewProvider {
static var previews: some View {
let settings = SettingsStore()
return
Group {
NavigationView {
MRZEntryView()
}
.environmentObject(settings)
.environment( \.colorScheme, .light)
}
}
}
#endif

View File

@@ -1,90 +0,0 @@
//
// MRZScannerViewController.swift
// NFCPassportReaderApp
//
// Created by Andy Qua on 17/02/2021.
// Copyright © 2021 Andy Qua. All rights reserved.
//
import UIKit
import SwiftUI
import QKMRZScanner
// Wraps the QKMRZScanner component in a simple UIView that allows a scan of the MRZ area from a Passport/ID Card
struct MRZScanner: UIViewControllerRepresentable {
let completionHandler: (String,Date,Date) -> Void
func makeUIViewController(context: Context) -> MRZScannerViewController {
let vc = MRZScannerViewController()
vc.mrzScannerView.delegate = context.coordinator
return vc
}
func updateUIViewController(_ uiViewController: MRZScannerViewController, context: Context) {
}
func makeCoordinator() -> Coordinator {
return Coordinator(completionHandler: completionHandler)
}
final class Coordinator: NSObject, QKMRZScannerViewDelegate {
let completionHandler: (String,Date,Date) -> Void
init(completionHandler: @escaping (String,Date,Date) -> Void) {
self.completionHandler = completionHandler
}
func mrzScannerView(_ mrzScannerView: QKMRZScannerView, didFind scanResult: QKMRZScanResult) {
print(scanResult)
if let dob = scanResult.birthdate, let doe = scanResult.expiryDate {
completionHandler(scanResult.documentNumber, dob, doe)
}
}
}
}
// MARK: UIViewController implementation
class MRZScannerViewController: UIViewController {
let mrzScannerView = QKMRZScannerView()
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Scan Passport"
self.navigationController?.title = "Scan passport"
let lbl = UILabel()
lbl.text = "Please scan the Machine Readable Zone."
lbl.numberOfLines = 0
self.view.addSubview(mrzScannerView)
self.view.addSubview(lbl)
mrzScannerView.translatesAutoresizingMaskIntoConstraints = false
mrzScannerView.topAnchor.constraint(equalTo: view.topAnchor, constant:50).isActive = true
mrzScannerView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
mrzScannerView.widthAnchor.constraint(equalToConstant: view.bounds.width).isActive = true
mrzScannerView.heightAnchor.constraint(equalToConstant: view.bounds.width).isActive = true
lbl.translatesAutoresizingMaskIntoConstraints = false
lbl.leadingAnchor.constraint(equalTo: mrzScannerView.leadingAnchor, constant: 10).isActive = true
lbl.topAnchor.constraint(equalTo: mrzScannerView.bottomAnchor, constant: 10).isActive = true
lbl.trailingAnchor.constraint(equalTo: mrzScannerView.trailingAnchor, constant: 10).isActive = true
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
mrzScannerView.startScanning()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
mrzScannerView.stopScanning()
}
}
extension MRZScannerViewController : QKMRZScannerViewDelegate {
func mrzScannerView(_ mrzScannerView: QKMRZScannerView, didFind scanResult: QKMRZScanResult) {
print(scanResult)
}
}

Some files were not shown because too many files have changed in this diff Show More