@vppos/react-native-nfc 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/NFCSDK.podspec +40 -0
- package/android/build.gradle +85 -0
- package/android/gradle.properties +5 -0
- package/android/src/main/AndroidManifest.xml +31 -0
- package/android/src/main/AndroidManifestNew.xml +30 -0
- package/android/src/main/java/com/nfcsdk/ChipReader.kt +237 -0
- package/android/src/main/java/com/nfcsdk/NFCSDKModule.kt +78 -0
- package/android/src/main/java/com/nfcsdk/NFCSDKPackage.kt +17 -0
- package/android/src/main/java/com/nfcsdk/NFCScanActivity.kt +299 -0
- package/android/src/main/java/com/nfcsdk/utils/Dg13Parser.kt +278 -0
- package/android/src/main/java/com/nfcsdk/utils/FaceExtractor.kt +40 -0
- package/android/src/main/java/com/nfcsdk/utils/MrzUtils.kt +75 -0
- package/android/src/main/res/drawable/bg_nfc_bottom_sheet.xml +13 -0
- package/android/src/main/res/drawable/bg_nfc_sheet_handle.xml +9 -0
- package/android/src/main/res/layout/activity_nfc.xml +110 -0
- package/android/src/main/res/values/styles.xml +10 -0
- package/android/src/main/res/xml/nfc_tech_filter.xml +8 -0
- package/ios/ChipReader.swift +258 -0
- package/ios/NFCSDK-Bridging-Header.h +2 -0
- package/ios/NFCSDK.mm +9 -0
- package/ios/NFCSDK.swift +112 -0
- package/ios/NFCSDKSession.swift +5 -0
- package/ios/utils/DG13Parser.swift +302 -0
- package/ios/utils/MrzUtils.swift +49 -0
- package/lib/module/errors.js +9 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/index.js +118 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/errors.d.ts +4 -0
- package/lib/typescript/src/errors.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +80 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +45 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/package.json +155 -0
- package/src/errors.ts +6 -0
- package/src/index.tsx +141 -0
- package/src/types.ts +45 -0
- package/vendor/ios-passport-reader/CHANGELOG +362 -0
- package/vendor/ios-passport-reader/CODE_OF_CONDUCT.md +77 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/AppDelegate.swift +39 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/Contents.json +158 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-40.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-72.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-76.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-small-50.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-small-50@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-small.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-small@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-small@3x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/ios-marketing.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/notification-icon@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/notification-icon@3x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/notification-icon~ipad.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/notification-icon~ipad@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/Contents.json +6 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/background.imageset/Contents.json +21 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/background.imageset/background.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/head.imageset/Contents.json +21 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Assets.xcassets/head.imageset/head.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Base.lproj/LaunchScreen.storyboard +25 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Extensions/FileManagerExt.swift +16 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Extensions/StringExt.swift +40 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Extensions/UIApplicationExt.swift +21 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Info.plist +77 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Model/PassportUtils.swift +76 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Model/SettingsStore.swift +107 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/NFCPassportReader.entitlements +10 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/SceneDelegate.swift +57 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Views/DetailsView.swift +197 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Views/ExportPassportView.swift +164 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Views/HelperViews/CheckBoxView.swift +48 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Views/HelperViews/ViewExt.swift +20 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Views/HelperViews/ViewModifiers.swift +41 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Views/MRZEntryView.swift +125 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Views/MRZScannerViewController.swift +90 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Views/MainView.swift +214 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Views/PassportSummaryView.swift +111 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Views/PassportView.swift +73 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Views/SettingsView.swift +63 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/Views/StoredPassportView.swift +152 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/masterList.pem +32 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp/readme.md +10 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp.xcodeproj/project.pbxproj +695 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp.xcodeproj/xcshareddata/xcschemes/NFCPassportReader.xcscheme +106 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp.xcworkspace/contents.xcworkspacedata +10 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderApp.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +8 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderAppTests/DataGroupParsingTests.swift +189 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderAppTests/Info.plist +22 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderAppTests/NFCPassportReaderTests.swift +260 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/NFCPassportReaderAppTests/PACETests.swift +112 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/Podfile +22 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/Podfile.lock +35 -0
- package/vendor/ios-passport-reader/Examples/Example_CocoaPods/README.md +2 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/AppDelegate.swift +39 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/Contents.json +158 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-40.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-72.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-72@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-76.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-small-50.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-small-50@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-small.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-small@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon-small@3x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/icon@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/ios-marketing.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/notification-icon@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/notification-icon@3x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/notification-icon~ipad.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/AppIcon.appiconset/notification-icon~ipad@2x.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/Contents.json +6 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/background.imageset/Contents.json +21 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/background.imageset/background.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/head.imageset/Contents.json +21 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Assets.xcassets/head.imageset/head.png +0 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Base.lproj/LaunchScreen.storyboard +25 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Extensions/FileManagerExt.swift +16 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Extensions/StringExt.swift +40 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Extensions/UIApplicationExt.swift +21 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Info.plist +79 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Model/PassportUtils.swift +99 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Model/SettingsStore.swift +98 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Model/SettingsStoreCAN.swift +75 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/MrzScanner/LICENSE +21 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/MrzScanner/PreviewView.swift +34 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/MrzScanner/StringUtils.swift +160 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/MrzScanner/ViewController.swift +320 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/MrzScanner/VisionViewController.swift +163 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/NFCPassportReader.entitlements +10 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/SceneDelegate.swift +58 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/CANViews/CanKeyView.swift +251 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/CANViews/MRZEntryViewCanKey.swift +65 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/CANViews/PassportViewCAN.swift +73 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/DetailsView.swift +193 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/ExportPassportView.swift +164 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/HelperViews/CheckBoxView.swift +48 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/HelperViews/ViewExt.swift +20 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/HelperViews/ViewModifiers.swift +41 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/MRZEntryView.swift +125 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/MRZScannerViewController.swift +90 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/MainView.swift +264 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/PassportSummaryView.swift +111 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/PassportView.swift +73 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/SettingsView.swift +47 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/Views/StoredPassportView.swift +149 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/masterList.pem +32 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp/readme.md +10 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp.xcodeproj/project.pbxproj +683 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +25 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderApp.xcodeproj/xcshareddata/xcschemes/NFCPassportReader.xcscheme +106 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderAppTests/DataGroupParsingTests.swift +190 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderAppTests/Info.plist +22 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderAppTests/NFCPassportReaderTests.swift +260 -0
- package/vendor/ios-passport-reader/Examples/Example_SPM/NFCPassportReaderAppTests/PACETests.swift +112 -0
- package/vendor/ios-passport-reader/LICENSE +21 -0
- package/vendor/ios-passport-reader/NFCPassportReader.podspec +27 -0
- package/vendor/ios-passport-reader/Package.swift +29 -0
- package/vendor/ios-passport-reader/README.md +141 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/AES_3DES_DESEncryption.swift +377 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/BACHandler.swift +194 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/ChipAuthenticationHandler.swift +224 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroupHash.swift +16 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroupParser.swift +36 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/ActiveAuthenticationInfo.swift +69 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/COM.swift +61 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/CardAccess.swift +38 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/ChipAuthenticationInfo.swift +135 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/ChipAuthenticationPublicKeyInfo.swift +53 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/DataGroup.swift +103 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/DataGroup1.swift +111 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/DataGroup11.swift +66 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/DataGroup12.swift +75 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/DataGroup14.swift +37 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/DataGroup15.swift +46 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/DataGroup2.swift +163 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/DataGroup7.swift +46 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/DataGroupId.swift +105 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/NotImplementedDG.swift +16 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/PACEInfo.swift +415 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/SOD.swift +240 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/DataGroups/SecurityInfo.swift +136 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/Errors.swift +148 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/Logging.swift +32 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/Models/FaceImageInfo.swift +161 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/NFCPassportModel.swift +540 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/NFCViewDisplayMessage.swift +60 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/OpenSSLUtils.swift +705 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/PACEHandler.swift +627 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/PassportReader.swift +387 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/Resources/PrivacyInfo.xcprivacy +14 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/ResponseAPDU.swift +25 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/SecureMessaging.swift +301 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/SecureMessagingSessionKeyGenerator.swift +156 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/SimpleASN1DumpParser.swift +173 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/TagReader.swift +374 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/Utils.swift +430 -0
- package/vendor/ios-passport-reader/Sources/NFCPassportReader/X509Wrapper.swift +168 -0
- package/vendor/ios-passport-reader/scripts/README.md +45 -0
- package/vendor/ios-passport-reader/scripts/extract.py +197 -0
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
//
|
|
2
|
+
// NFCPassportModel.swift
|
|
3
|
+
// NFCPassportReader
|
|
4
|
+
//
|
|
5
|
+
// Created by Andy Qua on 29/10/2019.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
import Foundation
|
|
10
|
+
import OSLog
|
|
11
|
+
|
|
12
|
+
#if os(iOS)
|
|
13
|
+
import UIKit
|
|
14
|
+
#endif
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
public enum PassportAuthenticationStatus {
|
|
18
|
+
case notDone
|
|
19
|
+
case success
|
|
20
|
+
case failed
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@available(iOS 13, macOS 10.15, *)
|
|
24
|
+
public class NFCPassportModel {
|
|
25
|
+
|
|
26
|
+
public private(set) lazy var documentType : String = { return String( passportDataElements?["5F03"]?.first ?? "?" ) }()
|
|
27
|
+
public private(set) lazy var documentSubType : String = { return String( passportDataElements?["5F03"]?.last ?? "?" ) }()
|
|
28
|
+
public private(set) lazy var documentNumber : String = { return (passportDataElements?["5A"] ?? "?").replacingOccurrences(of: "<", with: "" ) }()
|
|
29
|
+
public private(set) lazy var issuingAuthority : String = { return passportDataElements?["5F28"] ?? "?" }()
|
|
30
|
+
public private(set) lazy var documentExpiryDate : String = { return passportDataElements?["59"] ?? "?" }()
|
|
31
|
+
public private(set) lazy var dateOfBirth : String = { return passportDataElements?["5F57"] ?? "?" }()
|
|
32
|
+
public private(set) lazy var gender : String = { return passportDataElements?["5F35"] ?? "?" }()
|
|
33
|
+
public private(set) lazy var nationality : String = { return passportDataElements?["5F2C"] ?? "?" }()
|
|
34
|
+
|
|
35
|
+
public private(set) lazy var lastName : String = {
|
|
36
|
+
return names[0].replacingOccurrences(of: "<", with: " " )
|
|
37
|
+
}()
|
|
38
|
+
|
|
39
|
+
public private(set) lazy var firstName : String = {
|
|
40
|
+
var name = ""
|
|
41
|
+
for i in 1 ..< names.count {
|
|
42
|
+
let fn = names[i].replacingOccurrences(of: "<", with: " " ).trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
|
43
|
+
name += fn + " "
|
|
44
|
+
}
|
|
45
|
+
return name.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
|
|
46
|
+
}()
|
|
47
|
+
|
|
48
|
+
public private(set) lazy var passportMRZ : String = { return passportDataElements?["5F1F"] ?? "NOT FOUND" }()
|
|
49
|
+
|
|
50
|
+
// Extract fields from DG11 if present
|
|
51
|
+
private lazy var names : [String] = {
|
|
52
|
+
guard let dg11 = dataGroupsRead[.DG11] as? DataGroup11,
|
|
53
|
+
let fullName = dg11.fullName?.components(separatedBy: "<<") else { return (passportDataElements?["5B"] ?? "?").components(separatedBy: "<<") }
|
|
54
|
+
return fullName
|
|
55
|
+
}()
|
|
56
|
+
|
|
57
|
+
public private(set) lazy var placeOfBirth : String? = {
|
|
58
|
+
guard let dg11 = dataGroupsRead[.DG11] as? DataGroup11,
|
|
59
|
+
let placeOfBirth = dg11.placeOfBirth else { return nil }
|
|
60
|
+
return placeOfBirth
|
|
61
|
+
}()
|
|
62
|
+
|
|
63
|
+
/// residence address
|
|
64
|
+
public private(set) lazy var residenceAddress : String? = {
|
|
65
|
+
guard let dg11 = dataGroupsRead[.DG11] as? DataGroup11,
|
|
66
|
+
let address = dg11.address else { return nil }
|
|
67
|
+
return address
|
|
68
|
+
}()
|
|
69
|
+
|
|
70
|
+
/// phone number
|
|
71
|
+
public private(set) lazy var phoneNumber : String? = {
|
|
72
|
+
guard let dg11 = dataGroupsRead[.DG11] as? DataGroup11,
|
|
73
|
+
let telephone = dg11.telephone else { return nil }
|
|
74
|
+
return telephone
|
|
75
|
+
}()
|
|
76
|
+
|
|
77
|
+
/// personal number
|
|
78
|
+
public private(set) lazy var personalNumber : String? = {
|
|
79
|
+
if let dg11 = dataGroupsRead[.DG11] as? DataGroup11,
|
|
80
|
+
let personalNumber = dg11.personalNumber { return personalNumber }
|
|
81
|
+
|
|
82
|
+
return (passportDataElements?["53"] ?? "?").replacingOccurrences(of: "<", with: "" )
|
|
83
|
+
}()
|
|
84
|
+
|
|
85
|
+
/// face image info
|
|
86
|
+
public private(set) lazy var faceImageInfo : FaceImageInfo? = {
|
|
87
|
+
guard let dg2 = dataGroupsRead[.DG2] as? DataGroup2 else { return nil }
|
|
88
|
+
|
|
89
|
+
return FaceImageInfo.from(dg2: dg2)
|
|
90
|
+
}()
|
|
91
|
+
|
|
92
|
+
public private(set) lazy var documentSigningCertificate : X509Wrapper? = {
|
|
93
|
+
return certificateSigningGroups[.documentSigningCertificate]
|
|
94
|
+
}()
|
|
95
|
+
|
|
96
|
+
public private(set) lazy var countrySigningCertificate : X509Wrapper? = {
|
|
97
|
+
return certificateSigningGroups[.issuerSigningCertificate]
|
|
98
|
+
}()
|
|
99
|
+
|
|
100
|
+
// Extract data from COM
|
|
101
|
+
public private(set) lazy var LDSVersion : String = {
|
|
102
|
+
guard let com = dataGroupsRead[.COM] as? COM else { return "Unknown" }
|
|
103
|
+
return com.version
|
|
104
|
+
}()
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
public private(set) lazy var dataGroupsPresent : [String] = {
|
|
108
|
+
guard let com = dataGroupsRead[.COM] as? COM else { return [] }
|
|
109
|
+
return com.dataGroupsPresent
|
|
110
|
+
}()
|
|
111
|
+
|
|
112
|
+
// Parsed datagroup hashes
|
|
113
|
+
public private(set) var dataGroupsAvailable = [DataGroupId]()
|
|
114
|
+
public private(set) var dataGroupsRead : [DataGroupId:DataGroup] = [:]
|
|
115
|
+
public private(set) var dataGroupHashes = [DataGroupId: DataGroupHash]()
|
|
116
|
+
|
|
117
|
+
public internal(set) var cardAccess : CardAccess?
|
|
118
|
+
public internal(set) var BACStatus : PassportAuthenticationStatus = .notDone
|
|
119
|
+
public internal(set) var PACEStatus : PassportAuthenticationStatus = .notDone
|
|
120
|
+
public internal(set) var chipAuthenticationStatus : PassportAuthenticationStatus = .notDone
|
|
121
|
+
|
|
122
|
+
public private(set) var passportCorrectlySigned : Bool = false
|
|
123
|
+
public private(set) var documentSigningCertificateVerified : Bool = false
|
|
124
|
+
public private(set) var passportDataNotTampered : Bool = false
|
|
125
|
+
public private(set) var activeAuthenticationPassed : Bool = false
|
|
126
|
+
public private(set) var activeAuthenticationChallenge : [UInt8] = []
|
|
127
|
+
public private(set) var activeAuthenticationSignature : [UInt8] = []
|
|
128
|
+
public private(set) var verificationErrors : [Error] = []
|
|
129
|
+
|
|
130
|
+
public var isPACESupported : Bool {
|
|
131
|
+
get {
|
|
132
|
+
if cardAccess?.paceInfo != nil {
|
|
133
|
+
return true
|
|
134
|
+
} else {
|
|
135
|
+
// We may not have stored the cardAccess so check the DG14
|
|
136
|
+
if let dg14 = dataGroupsRead[.DG14] as? DataGroup14,
|
|
137
|
+
(dg14.securityInfos.filter { ($0 as? PACEInfo) != nil }).count > 0 {
|
|
138
|
+
return true
|
|
139
|
+
}
|
|
140
|
+
return false
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
public var isChipAuthenticationSupported : Bool {
|
|
146
|
+
get {
|
|
147
|
+
if let dg14 = dataGroupsRead[.DG14] as? DataGroup14,
|
|
148
|
+
(dg14.securityInfos.filter { ($0 as? ChipAuthenticationPublicKeyInfo) != nil }).count > 0 {
|
|
149
|
+
|
|
150
|
+
return true
|
|
151
|
+
} else {
|
|
152
|
+
return false
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
#if os(iOS)
|
|
158
|
+
public var passportImage : UIImage? {
|
|
159
|
+
guard let dg2 = dataGroupsRead[.DG2] as? DataGroup2 else { return nil }
|
|
160
|
+
|
|
161
|
+
return dg2.getImage()
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
public var signatureImage : UIImage? {
|
|
165
|
+
guard let dg7 = dataGroupsRead[.DG7] as? DataGroup7 else { return nil }
|
|
166
|
+
|
|
167
|
+
return dg7.getImage()
|
|
168
|
+
}
|
|
169
|
+
#endif
|
|
170
|
+
|
|
171
|
+
public var activeAuthenticationSupported : Bool {
|
|
172
|
+
guard let dg15 = dataGroupsRead[.DG15] as? DataGroup15 else { return false }
|
|
173
|
+
if dg15.ecdsaPublicKey != nil || dg15.rsaPublicKey != nil {
|
|
174
|
+
return true
|
|
175
|
+
}
|
|
176
|
+
return false
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private var certificateSigningGroups : [CertificateType:X509Wrapper] = [:]
|
|
180
|
+
|
|
181
|
+
private var passportDataElements : [String:String]? {
|
|
182
|
+
guard let dg1 = dataGroupsRead[.DG1] as? DataGroup1 else { return nil }
|
|
183
|
+
|
|
184
|
+
return dg1.elements
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
public init() {
|
|
189
|
+
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
public init( from dump: [String:String] ) {
|
|
193
|
+
var AAChallenge : [UInt8]?
|
|
194
|
+
var AASignature : [UInt8]?
|
|
195
|
+
for (key,value) in dump {
|
|
196
|
+
if let data = Data(base64Encoded: value) {
|
|
197
|
+
let bin = [UInt8](data)
|
|
198
|
+
if key == "AASignature" {
|
|
199
|
+
AASignature = bin
|
|
200
|
+
} else if key == "AAChallenge" {
|
|
201
|
+
AAChallenge = bin
|
|
202
|
+
} else {
|
|
203
|
+
do {
|
|
204
|
+
let dg = try DataGroupParser().parseDG(data: bin)
|
|
205
|
+
let dgId = DataGroupId.getIDFromName(name:key)
|
|
206
|
+
self.addDataGroup( dgId, dataGroup:dg )
|
|
207
|
+
} catch {
|
|
208
|
+
Logger.passportReader.error("Failed to import Datagroup - \(key) from dump - \(error)" )
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// See if we have Active Auth info in the dump
|
|
215
|
+
if let challenge = AAChallenge, let signature = AASignature {
|
|
216
|
+
verifyActiveAuthentication(challenge: challenge, signature: signature)
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
public func addDataGroup(_ id : DataGroupId, dataGroup: DataGroup ) {
|
|
221
|
+
self.dataGroupsRead[id] = dataGroup
|
|
222
|
+
if id != .COM && id != .SOD {
|
|
223
|
+
self.dataGroupsAvailable.append( id )
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
public func getDataGroup( _ id : DataGroupId ) -> DataGroup? {
|
|
228
|
+
return dataGroupsRead[id]
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/// Dumps the passport data
|
|
232
|
+
/// - Parameters:
|
|
233
|
+
/// selectedDataGroups - the Data Groups to be exported (if they are present in the passport)
|
|
234
|
+
/// includeActiveAutheticationData - Whether to include the Active Authentication challenge and response (if supported and retrieved)
|
|
235
|
+
/// - Returns: dictionary of DataGroup ids and Base64 encoded data
|
|
236
|
+
public func dumpPassportData( selectedDataGroups : [DataGroupId], includeActiveAuthenticationData : Bool = false) -> [String:String] {
|
|
237
|
+
var ret = [String:String]()
|
|
238
|
+
for dg in selectedDataGroups {
|
|
239
|
+
if let dataGroup = self.dataGroupsRead[dg] {
|
|
240
|
+
let val = Data(dataGroup.data)
|
|
241
|
+
let base64 = val.base64EncodedString()
|
|
242
|
+
ret[dg.getName()] = base64
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
if includeActiveAuthenticationData && self.activeAuthenticationSupported {
|
|
246
|
+
ret["AAChallenge"] = Data(activeAuthenticationChallenge).base64EncodedString()
|
|
247
|
+
ret["AASignature"] = Data(activeAuthenticationSignature).base64EncodedString()
|
|
248
|
+
}
|
|
249
|
+
return ret
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
public func getHashesForDatagroups( hashAlgorythm: String ) -> [DataGroupId:[UInt8]] {
|
|
253
|
+
var ret = [DataGroupId:[UInt8]]()
|
|
254
|
+
|
|
255
|
+
for (key, value) in dataGroupsRead {
|
|
256
|
+
if hashAlgorythm == "SHA1" {
|
|
257
|
+
ret[key] = calcSHA1Hash(value.body)
|
|
258
|
+
} else if hashAlgorythm == "SHA224" {
|
|
259
|
+
ret[key] = calcSHA224Hash(value.body)
|
|
260
|
+
} else if hashAlgorythm == "SHA256" {
|
|
261
|
+
ret[key] = calcSHA256Hash(value.body)
|
|
262
|
+
} else if hashAlgorythm == "SHA384" {
|
|
263
|
+
ret[key] = calcSHA384Hash(value.body)
|
|
264
|
+
} else if hashAlgorythm == "SHA512" {
|
|
265
|
+
ret[key] = calcSHA512Hash(value.body)
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return ret
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
/// This method performs the passive authentication
|
|
274
|
+
/// Passive Authentication : Two Parts:
|
|
275
|
+
/// Part 1 - Has the SOD (Security Object Document) been signed by a valid country signing certificate authority (CSCA)?
|
|
276
|
+
/// Part 2 - has it been tampered with (e.g. hashes of Datagroups match those in the SOD?
|
|
277
|
+
/// guard let sod = model.getDataGroup(.SOD) else { return }
|
|
278
|
+
///
|
|
279
|
+
/// - Parameter masterListURL: the path to the masterlist to try to verify the document signing certiifcate in the SOD
|
|
280
|
+
/// - Parameter useCMSVerification: Should we use OpenSSL CMS verification to verify the SOD content
|
|
281
|
+
/// is correctly signed by the document signing certificate OR should we do this manully based on RFC5652
|
|
282
|
+
/// CMS fails under certain circumstances (e.g. hashes are SHA512 whereas content is signed with SHA256RSA).
|
|
283
|
+
/// Currently defaulting to manual verification - hoping this will replace the CMS verification totally
|
|
284
|
+
/// CMS Verification currently there just in case
|
|
285
|
+
public func verifyPassport( masterListURL: URL?, useCMSVerification : Bool = false ) {
|
|
286
|
+
if let masterListURL = masterListURL {
|
|
287
|
+
do {
|
|
288
|
+
try validateAndExtractSigningCertificates( masterListURL: masterListURL )
|
|
289
|
+
} catch let error {
|
|
290
|
+
verificationErrors.append( error )
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
do {
|
|
295
|
+
try ensureReadDataNotBeenTamperedWith( useCMSVerification : useCMSVerification )
|
|
296
|
+
} catch let error {
|
|
297
|
+
verificationErrors.append( error )
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
public func verifyActiveAuthentication( challenge: [UInt8], signature: [UInt8] ) {
|
|
302
|
+
self.activeAuthenticationChallenge = challenge
|
|
303
|
+
self.activeAuthenticationSignature = signature
|
|
304
|
+
|
|
305
|
+
Logger.passportReader.debug( "Active Authentication")
|
|
306
|
+
Logger.passportReader.debug( " challange - \(binToHexRep(challenge))")
|
|
307
|
+
Logger.passportReader.debug( " signature - \(binToHexRep(signature))")
|
|
308
|
+
|
|
309
|
+
// Get AA Public key
|
|
310
|
+
self.activeAuthenticationPassed = false
|
|
311
|
+
guard let dg15 = self.dataGroupsRead[.DG15] as? DataGroup15 else { return }
|
|
312
|
+
if let rsaKey = dg15.rsaPublicKey {
|
|
313
|
+
do {
|
|
314
|
+
var decryptedSig = try OpenSSLUtils.decryptRSASignature(signature: Data(signature), pubKey: rsaKey)
|
|
315
|
+
|
|
316
|
+
// Decrypted signature compromises of header (6A), Message, Digest hash, Trailer
|
|
317
|
+
// Trailer can be 1 byte (BC - SHA-1 hash) or 2 bytes (xxCC) - where xx identifies the hash algorithm used
|
|
318
|
+
|
|
319
|
+
// if the last byte of the digest is 0xBC, then this uses dedicated hash function 3 (SHA-1),
|
|
320
|
+
// If the last byte is 0xCC, then the preceding byte tells you which hash function
|
|
321
|
+
// should be used (currently not yet implemented!)
|
|
322
|
+
// See ISO/IEC9796-2 for details on the verification and ISO/IEC 10118-3 for the dedicated hash functions!
|
|
323
|
+
var hashTypeByte = decryptedSig.popLast() ?? 0x00
|
|
324
|
+
if hashTypeByte == 0xCC {
|
|
325
|
+
hashTypeByte = decryptedSig.popLast() ?? 0x00
|
|
326
|
+
}
|
|
327
|
+
var hashType : String = ""
|
|
328
|
+
var hashLength = 0
|
|
329
|
+
|
|
330
|
+
switch hashTypeByte {
|
|
331
|
+
case 0xBC, 0x33:
|
|
332
|
+
hashType = "SHA1"
|
|
333
|
+
hashLength = 20 // 160 bits for SHA-1 -> 20 bytes
|
|
334
|
+
case 0x34:
|
|
335
|
+
hashType = "SHA256"
|
|
336
|
+
hashLength = 32 // 256 bits for SHA-256 -> 32 bytes
|
|
337
|
+
case 0x35:
|
|
338
|
+
hashType = "SHA512"
|
|
339
|
+
hashLength = 64 // 512 bits for SHA-512 -> 64 bytes
|
|
340
|
+
case 0x36:
|
|
341
|
+
hashType = "SHA384"
|
|
342
|
+
hashLength = 48 // 384 bits for SHA-384 -> 48 bytes
|
|
343
|
+
case 0x38:
|
|
344
|
+
hashType = "SHA224"
|
|
345
|
+
hashLength = 28 // 224 bits for SHA-224 -> 28 bytes
|
|
346
|
+
default:
|
|
347
|
+
Logger.passportReader.error( "Error identifying Active Authentication RSA message digest hash algorithm" )
|
|
348
|
+
return
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
let message = [UInt8](decryptedSig[1 ..< (decryptedSig.count-hashLength)])
|
|
352
|
+
let digest = [UInt8](decryptedSig[(decryptedSig.count-hashLength)...])
|
|
353
|
+
|
|
354
|
+
// Concatenate the challenge to the end of the message
|
|
355
|
+
let fullMsg = message + challenge
|
|
356
|
+
|
|
357
|
+
// Then generate the hash
|
|
358
|
+
let msgHash : [UInt8] = try calcHash(data: fullMsg, hashAlgorithm: hashType)
|
|
359
|
+
|
|
360
|
+
// Check hashes match
|
|
361
|
+
if msgHash == digest {
|
|
362
|
+
self.activeAuthenticationPassed = true
|
|
363
|
+
Logger.passportReader.debug( "Active Authentication (RSA) successful" )
|
|
364
|
+
} else {
|
|
365
|
+
Logger.passportReader.error( "Error verifying Active Authentication RSA signature - Hash doesn't match" )
|
|
366
|
+
}
|
|
367
|
+
} catch {
|
|
368
|
+
Logger.passportReader.error( "Error verifying Active Authentication RSA signature - \(error)" )
|
|
369
|
+
}
|
|
370
|
+
} else if let ecdsaPublicKey = dg15.ecdsaPublicKey {
|
|
371
|
+
var digestType = ""
|
|
372
|
+
if let dg14 = dataGroupsRead[.DG14] as? DataGroup14,
|
|
373
|
+
let aa = dg14.securityInfos.compactMap({ $0 as? ActiveAuthenticationInfo }).first {
|
|
374
|
+
digestType = aa.getSignatureAlgorithmOIDString() ?? ""
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
if OpenSSLUtils.verifyECDSASignature( publicKey:ecdsaPublicKey, signature: signature, data: challenge, digestType: digestType ) {
|
|
378
|
+
self.activeAuthenticationPassed = true
|
|
379
|
+
Logger.passportReader.debug( "Active Authentication (ECDSA) successful" )
|
|
380
|
+
} else {
|
|
381
|
+
Logger.passportReader.error( "Error verifying Active Authentication ECDSA signature" )
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// Check if signing certificate is on the revocation list
|
|
387
|
+
// We do this by trying to build a trust chain of the passport certificate against the ones in the revocation list
|
|
388
|
+
// and if we are successful then its been revoked.
|
|
389
|
+
// NOTE - NOT USED YET AS NOT ABLE TO TEST
|
|
390
|
+
func hasCertBeenRevoked( revocationListURL : URL ) -> Bool {
|
|
391
|
+
var revoked = false
|
|
392
|
+
do {
|
|
393
|
+
try validateAndExtractSigningCertificates( masterListURL: revocationListURL )
|
|
394
|
+
|
|
395
|
+
// Certificate chain found - which means certificate is on revocation list
|
|
396
|
+
revoked = true
|
|
397
|
+
} catch {
|
|
398
|
+
// No chain found - certificate not revoked
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
return revoked
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
private func validateAndExtractSigningCertificates( masterListURL: URL ) throws {
|
|
405
|
+
self.passportCorrectlySigned = false
|
|
406
|
+
|
|
407
|
+
guard let sod = getDataGroup(.SOD) else {
|
|
408
|
+
throw PassiveAuthenticationError.SODMissing("No SOD found" )
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
let data = Data(sod.body)
|
|
412
|
+
let cert = try OpenSSLUtils.getX509CertificatesFromPKCS7( pkcs7Der: data ).first!
|
|
413
|
+
self.certificateSigningGroups[.documentSigningCertificate] = cert
|
|
414
|
+
|
|
415
|
+
let rc = OpenSSLUtils.verifyTrustAndGetIssuerCertificate( x509:cert, CAFile: masterListURL )
|
|
416
|
+
switch rc {
|
|
417
|
+
case .success(let csca):
|
|
418
|
+
self.certificateSigningGroups[.issuerSigningCertificate] = csca
|
|
419
|
+
case .failure(let error):
|
|
420
|
+
throw error
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
Logger.passportReader.debug( "Passport passed SOD Verification" )
|
|
424
|
+
self.passportCorrectlySigned = true
|
|
425
|
+
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
private func ensureReadDataNotBeenTamperedWith( useCMSVerification: Bool ) throws {
|
|
429
|
+
guard let sod = getDataGroup(.SOD) as? SOD else {
|
|
430
|
+
throw PassiveAuthenticationError.SODMissing("No SOD found" )
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// Get SOD Content and verify that its correctly signed by the Document Signing Certificate
|
|
434
|
+
var signedData : Data
|
|
435
|
+
documentSigningCertificateVerified = false
|
|
436
|
+
do {
|
|
437
|
+
if useCMSVerification {
|
|
438
|
+
signedData = try OpenSSLUtils.verifyAndReturnSODEncapsulatedDataUsingCMS(sod: sod)
|
|
439
|
+
} else {
|
|
440
|
+
signedData = try OpenSSLUtils.verifyAndReturnSODEncapsulatedData(sod: sod)
|
|
441
|
+
}
|
|
442
|
+
documentSigningCertificateVerified = true
|
|
443
|
+
} catch {
|
|
444
|
+
signedData = try sod.getEncapsulatedContent()
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
// Now Verify passport data by comparing compare Hashes in SOD against
|
|
448
|
+
// computed hashes to ensure data not been tampered with
|
|
449
|
+
passportDataNotTampered = false
|
|
450
|
+
let asn1Data = try OpenSSLUtils.ASN1Parse( data: signedData )
|
|
451
|
+
let (sodHashAlgorythm, sodHashes) = try parseSODSignatureContent( asn1Data )
|
|
452
|
+
|
|
453
|
+
var errors : String = ""
|
|
454
|
+
for (id,dgVal) in dataGroupsRead {
|
|
455
|
+
guard let sodHashVal = sodHashes[id] else {
|
|
456
|
+
// SOD and COM don't have hashes so these aren't errors
|
|
457
|
+
if id != .SOD && id != .COM {
|
|
458
|
+
errors += "DataGroup \(id) is missing!\n"
|
|
459
|
+
}
|
|
460
|
+
continue
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
let computedHashVal = binToHexRep(dgVal.hash(sodHashAlgorythm))
|
|
464
|
+
|
|
465
|
+
var match = true
|
|
466
|
+
if computedHashVal != sodHashVal {
|
|
467
|
+
errors += "\(id) invalid hash:\n SOD hash:\(sodHashVal)\n Computed hash:\(computedHashVal)\n"
|
|
468
|
+
match = false
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
dataGroupHashes[id] = DataGroupHash(id: id.getName(), sodHash:sodHashVal, computedHash:computedHashVal, match:match)
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
if errors != "" {
|
|
475
|
+
Logger.passportReader.error( "HASH ERRORS - \(errors)" )
|
|
476
|
+
throw PassiveAuthenticationError.InvalidDataGroupHash(errors)
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
Logger.passportReader.debug( "Passport passed Datagroup Tampering check" )
|
|
480
|
+
passportDataNotTampered = true
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
/// Parses an text ASN1 structure, and extracts the Hash Algorythm and Hashes contained from the Octect strings
|
|
485
|
+
/// - Parameter content: the text ASN1 stucure format
|
|
486
|
+
/// - Returns: The Hash Algorythm used - either SHA1 or SHA256, and a dictionary of hashes for the datagroups (currently only DG1 and DG2 are handled)
|
|
487
|
+
private func parseSODSignatureContent( _ content : String ) throws -> (String, [DataGroupId : String]){
|
|
488
|
+
var currentDG = ""
|
|
489
|
+
var sodHashAlgo = ""
|
|
490
|
+
var sodHashes : [DataGroupId : String] = [:]
|
|
491
|
+
|
|
492
|
+
let lines = content.components(separatedBy: "\n")
|
|
493
|
+
|
|
494
|
+
let dgList : [DataGroupId] = [.COM,.DG1,.DG2,.DG3,.DG4,.DG5,.DG6,.DG7,.DG8,.DG9,.DG10,.DG11,.DG12,.DG13,.DG14,.DG15,.DG16,.SOD]
|
|
495
|
+
|
|
496
|
+
for line in lines {
|
|
497
|
+
if line.contains( "d=2" ) && line.contains( "OBJECT" ) {
|
|
498
|
+
if line.contains( "sha1" ) {
|
|
499
|
+
sodHashAlgo = "SHA1"
|
|
500
|
+
} else if line.contains( "sha224" ) {
|
|
501
|
+
sodHashAlgo = "SHA224"
|
|
502
|
+
} else if line.contains( "sha256" ) {
|
|
503
|
+
sodHashAlgo = "SHA256"
|
|
504
|
+
} else if line.contains( "sha384" ) {
|
|
505
|
+
sodHashAlgo = "SHA384"
|
|
506
|
+
} else if line.contains( "sha512" ) {
|
|
507
|
+
sodHashAlgo = "SHA512"
|
|
508
|
+
}
|
|
509
|
+
} else if line.contains("d=3" ) && line.contains( "INTEGER" ) {
|
|
510
|
+
if let range = line.range(of: "INTEGER") {
|
|
511
|
+
let substr = line[range.upperBound..<line.endIndex]
|
|
512
|
+
if let r2 = substr.range(of: ":") {
|
|
513
|
+
currentDG = String(line[r2.upperBound...])
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
} else if line.contains("d=3" ) && line.contains( "OCTET STRING" ) {
|
|
518
|
+
if let range = line.range(of: "[HEX DUMP]:") {
|
|
519
|
+
let val = line[range.upperBound..<line.endIndex]
|
|
520
|
+
if currentDG != "", let id = Int(currentDG, radix:16) {
|
|
521
|
+
sodHashes[dgList[id]] = String(val)
|
|
522
|
+
currentDG = ""
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if sodHashAlgo == "" {
|
|
529
|
+
throw PassiveAuthenticationError.UnableToParseSODHashes("Unable to find hash algorythm used" )
|
|
530
|
+
}
|
|
531
|
+
if sodHashes.count == 0 {
|
|
532
|
+
throw PassiveAuthenticationError.UnableToParseSODHashes("Unable to extract hashes" )
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
Logger.passportReader.debug( "Parse SOD - Using Algo - \(sodHashAlgo)" )
|
|
536
|
+
Logger.passportReader.debug( " - Hashes - \(sodHashes)" )
|
|
537
|
+
|
|
538
|
+
return (sodHashAlgo, sodHashes)
|
|
539
|
+
}
|
|
540
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
//
|
|
2
|
+
// NFCViewDisplayMessage.swift
|
|
3
|
+
// NFCPassportReader
|
|
4
|
+
//
|
|
5
|
+
// Created by Andy Qua on 09/02/2021.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
|
|
10
|
+
@available(iOS 13, macOS 10.15, *)
|
|
11
|
+
public enum NFCViewDisplayMessage {
|
|
12
|
+
case requestPresentPassport
|
|
13
|
+
case authenticatingWithPassport(Int)
|
|
14
|
+
case readingDataGroupProgress(DataGroupId, Int)
|
|
15
|
+
case error(NFCPassportReaderError)
|
|
16
|
+
case activeAuthentication
|
|
17
|
+
case successfulRead
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
@available(iOS 13, macOS 10.15, *)
|
|
21
|
+
extension NFCViewDisplayMessage {
|
|
22
|
+
public var description: String {
|
|
23
|
+
switch self {
|
|
24
|
+
case .requestPresentPassport:
|
|
25
|
+
return "Hold your iPhone near an NFC enabled passport."
|
|
26
|
+
case .authenticatingWithPassport(let progress):
|
|
27
|
+
let progressString = handleProgress(percentualProgress: progress)
|
|
28
|
+
return "Authenticating with passport.....\n\n\(progressString)"
|
|
29
|
+
case .readingDataGroupProgress(let dataGroup, let progress):
|
|
30
|
+
let progressString = handleProgress(percentualProgress: progress)
|
|
31
|
+
return "Reading \(dataGroup).....\n\n\(progressString)"
|
|
32
|
+
case .error(let tagError):
|
|
33
|
+
switch tagError {
|
|
34
|
+
case NFCPassportReaderError.TagNotValid:
|
|
35
|
+
return "Tag not valid."
|
|
36
|
+
case NFCPassportReaderError.MoreThanOneTagFound:
|
|
37
|
+
return "More than 1 tags was found. Please present only 1 tag."
|
|
38
|
+
case NFCPassportReaderError.ConnectionError:
|
|
39
|
+
return "Connection error. Please try again."
|
|
40
|
+
case NFCPassportReaderError.InvalidMRZKey:
|
|
41
|
+
return "MRZ Key not valid for this document."
|
|
42
|
+
case NFCPassportReaderError.ResponseError(let description, let sw1, let sw2):
|
|
43
|
+
return "Sorry, there was a problem reading the passport. \(description) - (0x\(sw1), 0x\(sw2)"
|
|
44
|
+
default:
|
|
45
|
+
return "Sorry, there was a problem reading the passport. Please try again"
|
|
46
|
+
}
|
|
47
|
+
case .activeAuthentication:
|
|
48
|
+
return "Authenticating....."
|
|
49
|
+
case .successfulRead:
|
|
50
|
+
return "Passport read successfully"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
func handleProgress(percentualProgress: Int) -> String {
|
|
55
|
+
let p = (percentualProgress/20)
|
|
56
|
+
let full = String(repeating: "🟢 ", count: p)
|
|
57
|
+
let empty = String(repeating: "⚪️ ", count: 5-p)
|
|
58
|
+
return "\(full)\(empty)"
|
|
59
|
+
}
|
|
60
|
+
}
|