diff --git a/.gitignore b/.gitignore index 893dcd36..02ae84c8 100644 --- a/.gitignore +++ b/.gitignore @@ -96,3 +96,7 @@ iOSInjectionProject/ /.DS_Store /Package.resolved /Sources/.DS_Store + +# Workspace configuration +Examples/Example_SPM/NFCPassportReaderApp.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +Examples/Example_SPM/NFCPassportReaderApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata diff --git a/Examples/Example_SPM/NFCPassportReaderApp.xcodeproj/project.pbxproj b/Examples/Example_SPM/NFCPassportReaderApp.xcodeproj/project.pbxproj index 7c7fc13b..fb41bee6 100644 --- a/Examples/Example_SPM/NFCPassportReaderApp.xcodeproj/project.pbxproj +++ b/Examples/Example_SPM/NFCPassportReaderApp.xcodeproj/project.pbxproj @@ -33,8 +33,6 @@ 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 */; }; @@ -83,8 +81,6 @@ A1DD3F3E22C535F00067255C /* masterList.pem */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = masterList.pem; sourceTree = ""; }; 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 = ""; }; - A1EBC5212370BAB2004DD19E /* DataGroupParsingTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataGroupParsingTests.swift; sourceTree = ""; }; - A1EBC5222370BAB2004DD19E /* NFCPassportReaderTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NFCPassportReaderTests.swift; sourceTree = ""; }; A1FDC52D25D3F15D00D22FF4 /* SettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsView.swift; sourceTree = ""; }; A1FDC53125D3F19E00D22FF4 /* ViewModifiers.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModifiers.swift; sourceTree = ""; }; A1FDC53325D3F1DE00D22FF4 /* CheckBoxView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheckBoxView.swift; sourceTree = ""; }; @@ -219,8 +215,6 @@ A1EBC50E2370B88D004DD19E /* NFCPassportReaderAppTests */ = { isa = PBXGroup; children = ( - A1EBC5212370BAB2004DD19E /* DataGroupParsingTests.swift */, - A1EBC5222370BAB2004DD19E /* NFCPassportReaderTests.swift */, A17375F425F78B0C005995DA /* PACETests.swift */, A1EBC5112370B88D004DD19E /* Info.plist */, ); @@ -367,9 +361,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - A1EBC5252370BAB2004DD19E /* NFCPassportReaderTests.swift in Sources */, A17375F525F78B0D005995DA /* PACETests.swift in Sources */, - A1EBC5242370BAB2004DD19E /* DataGroupParsingTests.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Examples/Example_SPM/NFCPassportReaderApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/Examples/Example_SPM/NFCPassportReaderApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 00000000..54044e54 --- /dev/null +++ b/Examples/Example_SPM/NFCPassportReaderApp.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,32 @@ +{ + "pins" : [ + { + "identity" : "mrzparser", + "kind" : "remoteSourceControl", + "location" : "https://github.com/appintheair/MRZParser", + "state" : { + "revision" : "64b73fae8092b31d0a378f0d000c244470c7ac44", + "version" : "1.1.3" + } + }, + { + "identity" : "nfcpassportreader", + "kind" : "remoteSourceControl", + "location" : "https://github.com/AndyQ/NFCPassportReader", + "state" : { + "revision" : "f685b40aebc5445ac591dc4e9b619d22bbe5279e", + "version" : "1.1.9" + } + }, + { + "identity" : "openssl", + "kind" : "remoteSourceControl", + "location" : "https://github.com/krzyzanowskim/OpenSSL.git", + "state" : { + "revision" : "0faf71a188bcfdf0245cab42886b9b240ca71c52", + "version" : "1.1.2200" + } + } + ], + "version" : 2 +} diff --git a/Package.swift b/Package.swift index 72fffade..66a5862a 100644 --- a/Package.swift +++ b/Package.swift @@ -24,6 +24,9 @@ let package = Package( .target( name: "NFCPassportReader", dependencies: ["OpenSSL"]), + .testTarget( + name: "NFCPassportReaderTests", + dependencies: ["NFCPassportReader", "OpenSSL"]), ] ) diff --git a/Sources/NFCPassportReader/DataGroups/DataGroupId.swift b/Sources/NFCPassportReader/DataGroups/DataGroupId.swift index 3f5f36d8..edca4283 100644 --- a/Sources/NFCPassportReader/DataGroups/DataGroupId.swift +++ b/Sources/NFCPassportReader/DataGroups/DataGroupId.swift @@ -56,7 +56,8 @@ public enum DataGroupId : Int, CaseIterable { static public func getIDFromName( name: String ) -> DataGroupId { switch( name ) { - case "COM": return .COM + // Name in DataGroupParser is "Common", not "COM". Supporting both so ID is added correctly + case "COM", "Common": return .COM case "DG1": return .DG1 case "DG2": return .DG2 case "DG3": return .DG3 @@ -73,7 +74,8 @@ public enum DataGroupId : Int, CaseIterable { case "DG14": return .DG14 case "DG15": return .DG15 case "DG16": return .DG16 - case "SOD": return .SOD + // Name in DataGroupParser is "SecurityData", not "SOD". Supporting both so ID is added correctly + case "SOD", "SecurityData": return .SOD default: return .Unknown } } diff --git a/Sources/NFCPassportReader/NFCPassportModel.swift b/Sources/NFCPassportReader/NFCPassportModel.swift index 24503ffc..4d506748 100644 --- a/Sources/NFCPassportReader/NFCPassportModel.swift +++ b/Sources/NFCPassportReader/NFCPassportModel.swift @@ -153,7 +153,7 @@ public class NFCPassportModel { } } } - + #if os(iOS) public var passportImage : UIImage? { guard let dg2 = dataGroupsRead[.DG2] as? DataGroup2 else { return nil } diff --git a/Sources/NFCPassportReader/PassportReader.swift b/Sources/NFCPassportReader/PassportReader.swift index ecfd47ae..7eeea528 100644 --- a/Sources/NFCPassportReader/PassportReader.swift +++ b/Sources/NFCPassportReader/PassportReader.swift @@ -292,12 +292,10 @@ extension PassportReader { var DGsToRead = [DataGroupId]() self.updateReaderSessionMessage( alertMessage: NFCViewDisplayMessage.readingDataGroupProgress(.COM, 0) ) + if let com = try await readDataGroup(tagReader:tagReader, dgId:.COM) as? COM { self.passport.addDataGroup( .COM, dataGroup:com ) - - // SOD and COM shouldn't be present in the DG list but just in case (worst case here we read the sod twice) - DGsToRead = [.SOD] + com.dataGroupsPresent.map { DataGroupId.getIDFromName(name:$0) } - DGsToRead.removeAll { $0 == .COM } + self.addDatagroupsToRead(com: com, to: &DGsToRead) } if DGsToRead.contains( .DG14 ) { @@ -385,6 +383,10 @@ extension PassportReader { // OK passport can't handle max length so drop it down tagReader.reduceDataReadingAmount() redoBAC = true + } else if errMsg == "UnsupportedDataGroup" { + // OK, this DataGroup is not supported, lets skip it + Logger.passportReader.debug("Unsupported DataGroup - \(dgId.rawValue)") + return nil } if redoBAC { @@ -409,5 +411,13 @@ extension PassportReader { nfcContinuation?.resume(throwing: error) nfcContinuation = nil } + + internal func addDatagroupsToRead(com: COM, to DGsToRead: inout [DataGroupId]) { + DGsToRead += com.dataGroupsPresent.compactMap { DataGroupId.getIDFromName(name:$0) } + DGsToRead.removeAll { $0 == .COM } + + // SOD should not be present in COM, but just in case we check before adding it so its not read twice + if !DGsToRead.contains(.SOD) { DGsToRead.insert(.SOD, at: 0) } + } } #endif diff --git a/Examples/Example_SPM/NFCPassportReaderAppTests/DataGroupParsingTests.swift b/Tests/NFCPassportReaderTests/DataGroupParsingTests.swift similarity index 100% rename from Examples/Example_SPM/NFCPassportReaderAppTests/DataGroupParsingTests.swift rename to Tests/NFCPassportReaderTests/DataGroupParsingTests.swift diff --git a/Examples/Example_SPM/NFCPassportReaderAppTests/NFCPassportReaderTests.swift b/Tests/NFCPassportReaderTests/NFCPassportReaderTests.swift similarity index 85% rename from Examples/Example_SPM/NFCPassportReaderAppTests/NFCPassportReaderTests.swift rename to Tests/NFCPassportReaderTests/NFCPassportReaderTests.swift index 32ce519a..4773c192 100644 --- a/Examples/Example_SPM/NFCPassportReaderAppTests/NFCPassportReaderTests.swift +++ b/Tests/NFCPassportReaderTests/NFCPassportReaderTests.swift @@ -1,6 +1,7 @@ import XCTest import CoreNFC import OpenSSL +import OSLog @testable import NFCPassportReader @@ -17,7 +18,8 @@ public func XCTAssertNoThrow(_ expression: @autoclosure () throws -> T, _ mes final class NFCPassportReaderTests: XCTestCase { - + let logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "tests") + func testBinToHexRep() { let val : [UInt8] = [0x12, 0x24, 0x55, 0x77] XCTAssertEqual( binToHexRep(val), "12245577" ) @@ -136,9 +138,9 @@ final class NFCPassportReaderTests: XCTestCase { let iv : [UInt8] = [0, 0, 0, 0, 0, 0, 0, 0] let key : [UInt8] = [191, 73, 56, 112, 158, 148, 146, 127, 157, 76, 117, 8, 239, 128, 87, 42] let enc = tripleDESEncrypt(key: key, message: msg, iv: iv) - Log.debug("KEY: \(binToHexRep(key))") - Log.debug("MSG: \(binToHexRep(msg))") - Log.debug("ENC: \(binToHexRep(enc))") + logger.debug("KEY: \(binToHexRep(key))") + logger.debug("MSG: \(binToHexRep(msg))") + logger.debug("ENC: \(binToHexRep(enc))") XCTAssertEqual( binToHexRep(enc), "4DAF068AB358BC9E8F5E916D3DEDE750D92315370E44D9B3" ) } @@ -148,9 +150,9 @@ final class NFCPassportReaderTests: XCTestCase { let iv : [UInt8] = [0, 0, 0, 0, 0, 0, 0, 0] let key : [UInt8] = [191, 73, 56, 112, 158, 148, 146, 127, 157, 76, 117, 8, 239, 128, 87, 42] let dec = tripleDESDecrypt(key: key, message: enc, iv: iv) - Log.debug("KEY: \(binToHexRep(key))") - Log.debug("ENC: \(binToHexRep(enc))") - Log.debug("DEC: \(binToHexRep(dec))") + logger.debug("KEY: \(binToHexRep(key))") + logger.debug("ENC: \(binToHexRep(enc))") + logger.debug("DEC: \(binToHexRep(dec))") let val = String(data:Data(dec), encoding:.utf8) XCTAssertEqual( val, "maryhadalittlelambaaaaaa" ) @@ -218,33 +220,32 @@ final class NFCPassportReaderTests: XCTestCase { } - func testConvertECDSAPlainTODer() { - let sigText = "67e147aac644325792dfa0b1615956dc4ed54e8cd859341571db98003431936e0651e9a3cdbcea3c8accd75a6f6bf07eb6bcf9ad1728e21aa854049e634e6fbf" - let sig = hexRepToBin(sigText) - - let ecsig = ECDSA_SIG_new() - defer { ECDSA_SIG_free(ecsig) } - sig.withUnsafeBufferPointer { (unsafeBufPtr) in - let unsafePointer = unsafeBufPtr.baseAddress! - let r = BN_bin2bn(unsafePointer, 32, nil) - let s = BN_bin2bn(unsafePointer + 32, 32, nil) - ECDSA_SIG_set0(ecsig, r, s) - } - - //print( "Sig - \(ecsig)" ) - - var derEncodedSignature: UnsafeMutablePointer? = nil - let derLength = i2d_ECDSA_SIG(ecsig, &derEncodedSignature) - - var derBytes = [UInt8](repeating: 0, count: Int(derLength)) - for b in 0..? = nil + let derLength = i2d_ECDSA_SIG(ecsig, &derEncodedSignature) + var derBytes = [UInt8](repeating: 0, count: Int(derLength)) + for b in 0..