From 0f176afced56aceb2e5506861402348536f54d97 Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Mon, 17 May 2021 16:32:12 +0300 Subject: [PATCH 1/4] Added zBase32 encoding functionallity; Added WKD url constructor; --- FlowCrypt.xcodeproj/project.pbxproj | 52 +++++- .../Compose/ComposeViewController.swift | 6 +- .../Inbox/InboxViewController.swift | 2 +- .../Backup Provider/Gmail+Backup.swift | 2 +- .../GmailService+folders.swift | 2 +- .../WKDURLs/WKDURLsCreator.swift | 40 +++++ .../DataExntensions+ZBase32Encoding.swift | 158 ++++++++++++++++++ .../{ => Data}/DataExtensions.swift | 0 .../WKDURLs/WKDURLsConstructorTests.swift | 59 +++++++ .../WKDURLs/ZBase32EncodingTests.swift | 19 +++ 10 files changed, 333 insertions(+), 7 deletions(-) create mode 100644 FlowCrypt/Functionality/WKDURLs/WKDURLsCreator.swift create mode 100644 FlowCryptCommon/Extensions/Data/DataExntensions+ZBase32Encoding.swift rename FlowCryptCommon/Extensions/{ => Data}/DataExtensions.swift (100%) create mode 100644 FlowCryptTests/Functionallity/WKDURLs/WKDURLsConstructorTests.swift create mode 100644 FlowCryptTests/Functionallity/WKDURLs/ZBase32EncodingTests.swift diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index a721e0631..22aa1d338 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -10,6 +10,11 @@ 04B4728D1ECE29D200B8266F /* KeyInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B4728B1ECE29D200B8266F /* KeyInfo.swift */; }; 04B472951ECE29F600B8266F /* MyMenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472921ECE29F600B8266F /* MyMenuViewController.swift */; }; 04B472961ECE29F600B8266F /* SideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472931ECE29F600B8266F /* SideMenuNavigationController.swift */; }; + 21CE25E62650070300ADFF4B /* WKDURLsCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21CE25E52650070300ADFF4B /* WKDURLsCreator.swift */; }; + 21F836A02652A19A00B2448C /* WKDURLsCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21CE25E52650070300ADFF4B /* WKDURLsCreator.swift */; }; + 21F836B62652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F836B52652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift */; }; + 21F836CC2652A38700B2448C /* ZBase32EncodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F836CB2652A38700B2448C /* ZBase32EncodingTests.swift */; }; + 21F836D32652A46E00B2448C /* WKDURLsConstructorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F836D22652A46E00B2448C /* WKDURLsConstructorTests.swift */; }; 32DCA00224982EDA88D69C6E /* AppErr.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DCA4B11D4531B3B04D01D1 /* AppErr.swift */; }; 32DCA04CA0DAB79C39514782 /* CoreTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DCAC732B988D9704658812 /* CoreTypes.swift */; }; 32DCA1414EEA727B86C337D5 /* Core.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DCA0C3D34A69851A238E87 /* Core.swift */; }; @@ -345,6 +350,10 @@ 069059B887A8580765029BF9 /* Pods_FlowCrypt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FlowCrypt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 113F04B20ECC35FC59A81A6C /* Pods-FlowCryptTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptTests.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptTests/Pods-FlowCryptTests.release.xcconfig"; sourceTree = ""; }; 11C1375F41411882DC4C9431 /* Pods-FlowCryptUIApplication.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptUIApplication.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptUIApplication/Pods-FlowCryptUIApplication.release.xcconfig"; sourceTree = ""; }; + 21CE25E52650070300ADFF4B /* WKDURLsCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKDURLsCreator.swift; sourceTree = ""; }; + 21F836B52652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataExntensions+ZBase32Encoding.swift"; sourceTree = ""; }; + 21F836CB2652A38700B2448C /* ZBase32EncodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZBase32EncodingTests.swift; sourceTree = ""; }; + 21F836D22652A46E00B2448C /* WKDURLsConstructorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKDURLsConstructorTests.swift; sourceTree = ""; }; 27D857C43583281B45F427F8 /* Pods-FlowCryptUI.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptUI.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptUI/Pods-FlowCryptUI.release.xcconfig"; sourceTree = ""; }; 32DCA058652FD4616FB04FB6 /* SequenceExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SequenceExtensions.swift; sourceTree = ""; }; 32DCA0C3D34A69851A238E87 /* Core.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Core.swift; sourceTree = ""; }; @@ -712,6 +721,40 @@ path = SideMenu; sourceTree = ""; }; + 21CE25D32650034500ADFF4B /* WKDURLs */ = { + isa = PBXGroup; + children = ( + 21CE25E52650070300ADFF4B /* WKDURLsCreator.swift */, + ); + path = WKDURLs; + sourceTree = ""; + }; + 21F836A62652A1B700B2448C /* Functionallity */ = { + isa = PBXGroup; + children = ( + 21F836A72652A1CD00B2448C /* WKDURLs */, + ); + path = Functionallity; + sourceTree = ""; + }; + 21F836A72652A1CD00B2448C /* WKDURLs */ = { + isa = PBXGroup; + children = ( + 21F836CB2652A38700B2448C /* ZBase32EncodingTests.swift */, + 21F836D22652A46E00B2448C /* WKDURLsConstructorTests.swift */, + ); + path = WKDURLs; + sourceTree = ""; + }; + 21F836B42652A25D00B2448C /* Data */ = { + isa = PBXGroup; + children = ( + 32DCAEFF16F5D91A35791730 /* DataExtensions.swift */, + 21F836B52652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift */, + ); + path = Data; + sourceTree = ""; + }; 2DC3601602226D74335E18F4 /* Pods */ = { isa = PBXGroup; children = ( @@ -1197,6 +1240,7 @@ A3DAD5FC22E4574B00F2C4CD /* FlowCryptTests */ = { isa = PBXGroup; children = ( + 21F836A62652A1B700B2448C /* Functionallity */, 9F3EF32923B15C9500FA0CEF /* ImapHelperTest.swift */, 5A39F438239ECDD0001F4607 /* ExtensionTests.swift */, A3DAD5FD22E4574B00F2C4CD /* FlowCryptCoreTests.swift */, @@ -1296,6 +1340,7 @@ C132B9C61EC2DCC000763715 /* Functionality */ = { isa = PBXGroup; children = ( + 21CE25D32650034500ADFF4B /* WKDURLs */, A370EAB6238697E000685215 /* Pgp */, D29AFFEE24092F4900C1387D /* DataManager */, 9FC4114A25961CD6001180A8 /* Mail Provider */, @@ -1404,6 +1449,7 @@ D254AA5F24092A9E0041CAE0 /* Extensions */ = { isa = PBXGroup; children = ( + 21F836B42652A25D00B2448C /* Data */, 9F56BD3723438C7000A7371A /* DateFormattingExtensions.swift */, 9F716304234FC7200031645E /* LocalizationExtensions.swift */, 9F56BD3923438D3700A7371A /* StyleExtension.swift */, @@ -1417,7 +1463,6 @@ 32DCA058652FD4616FB04FB6 /* SequenceExtensions.swift */, 32DCA38E87F2B7196E0E1F1F /* CodableExntensions.swift */, 9FD22A1B230FE7D0005067A6 /* Then.swift */, - 32DCAEFF16F5D91A35791730 /* DataExtensions.swift */, D271774D24255F1100BDA9A9 /* UIColorExtensions.swift */, D2FD0F682453245E00259FF0 /* Either.swift */, ); @@ -2203,6 +2248,7 @@ D212D35E24C1AACF00035991 /* PrvKeyInfo.swift in Sources */, 9F1D5769263B540100477938 /* Logger.swift in Sources */, A3DAD5FE22E4574B00F2C4CD /* FlowCryptCoreTests.swift in Sources */, + 21F836CC2652A38700B2448C /* ZBase32EncodingTests.swift in Sources */, D2A9CA45242622F800E1D898 /* GeneralConstantsTest.swift in Sources */, A3DAD60B22E458C300F2C4CD /* DataExtensions.swift in Sources */, A3DAD60822E4588800F2C4CD /* TestData.swift in Sources */, @@ -2216,6 +2262,7 @@ 5A39F439239ECDD0001F4607 /* ExtensionTests.swift in Sources */, D212D36524C1AC4800035991 /* KeyId.swift in Sources */, 9F003DBC25EA92D000EB38C0 /* LogOutHandler.swift in Sources */, + 21F836A02652A19A00B2448C /* WKDURLsCreator.swift in Sources */, 9F7DE8C5232029BD00F10B3E /* Core.swift in Sources */, 32DCAD6360C9EFF4FDD8EF6F /* DispatchTimeExtension.swift in Sources */, 9F7DE8C723202A0200F10B3E /* CoreHost.swift in Sources */, @@ -2223,6 +2270,7 @@ 9F003D9E25EA910B00EB38C0 /* LocalStorageTests.swift in Sources */, 32DCAF683D87EA6221F71335 /* SequenceExtensions.swift in Sources */, 9F589F11238C7DDC007FD759 /* User.swift in Sources */, + 21F836D32652A46E00B2448C /* WKDURLsConstructorTests.swift in Sources */, D2E26F6D24F263B600612AF1 /* KeyAlgo.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2247,6 +2295,7 @@ D20D3C752520AB9A00D4AA9A /* BackupService.swift in Sources */, C192421F1EC48B6900C3D251 /* SetupViewController.swift in Sources */, 9F0C3C2623194E0A00299985 /* FolderViewModel.swift in Sources */, + 21CE25E62650070300ADFF4B /* WKDURLsCreator.swift in Sources */, 9FC411212595EA12001180A8 /* MessageSearchProvider.swift in Sources */, D27B911D24EFE806002DF0A1 /* ContactObject.swift in Sources */, 9FDF3654235A218E00614596 /* main.swift in Sources */, @@ -2446,6 +2495,7 @@ D2CDC3CE2402CDB4002B045F /* DispatchTimeExtension.swift in Sources */, 9F44971626430710003A9FE9 /* Trace.swift in Sources */, D2CDC3CD2402CCD7002B045F /* UIImageExtensions.swift in Sources */, + 21F836B62652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift in Sources */, D29AFFF6240939AE00C1387D /* Then.swift in Sources */, D2531F3423FEEF5F007E5198 /* StyleExtension.swift in Sources */, D254AA6024092AB80041CAE0 /* TapTicFeedback.swift in Sources */, diff --git a/FlowCrypt/Controllers/Compose/ComposeViewController.swift b/FlowCrypt/Controllers/Compose/ComposeViewController.swift index 300b06ad9..17b80c2d1 100644 --- a/FlowCrypt/Controllers/Compose/ComposeViewController.swift +++ b/FlowCrypt/Controllers/Compose/ComposeViewController.swift @@ -324,7 +324,7 @@ extension ComposeViewController { private func isInputValid() -> Bool { let emails = recipients.map(\.email) - let hasContent = emails.filter { $0.hasContent } + let hasContent = emails.filter(\.hasContent) guard emails.count == hasContent.count else { showAlert(message: "compose_enter_recipient".localized) @@ -468,7 +468,7 @@ extension ComposeViewController { .onShouldReturn { [weak self] textField -> Bool in self?.shouldReturn(with: textField) ?? true } - .onShouldChangeCharacters { [weak self] (textField, character) -> (Bool) in + .onShouldChangeCharacters { [weak self] textField, character -> (Bool) in self?.shouldChange(with: textField, and: character) ?? true } .then { @@ -584,7 +584,7 @@ extension ComposeViewController { guard textField.text == "" else { return } let selectedRecipients = recipients - .filter { $0.state.isSelected } + .filter(\.state.isSelected) guard selectedRecipients.isEmpty else { // remove selected recipients diff --git a/FlowCrypt/Controllers/Inbox/InboxViewController.swift b/FlowCrypt/Controllers/Inbox/InboxViewController.swift index 82c35a15f..07cbb0de9 100644 --- a/FlowCrypt/Controllers/Inbox/InboxViewController.swift +++ b/FlowCrypt/Controllers/Inbox/InboxViewController.swift @@ -214,7 +214,7 @@ extension InboxViewController { // insert new messages let indexesToInsert = messageContext.messages .enumerated() - .map { (index, _) -> Int in + .map { index, _ -> Int in let indexInTableView = index + count return indexInTableView } diff --git a/FlowCrypt/Functionality/Mail Provider/Backup Provider/Gmail+Backup.swift b/FlowCrypt/Functionality/Mail Provider/Backup Provider/Gmail+Backup.swift index 753b04a16..90d15d85b 100644 --- a/FlowCrypt/Functionality/Mail Provider/Backup Provider/Gmail+Backup.swift +++ b/FlowCrypt/Functionality/Mail Provider/Backup Provider/Gmail+Backup.swift @@ -24,7 +24,7 @@ extension GmailService: BackupProvider { Logger.logVerbose("[GmailService] searching done, found \(backupMessages.count) backup messages") let uniqueMessages = Set(backupMessages) let attachments = uniqueMessages - .compactMap { (message) -> [(String, String)]? in + .compactMap { message -> [(String, String)]? in Logger.logVerbose("[GmailService] processing backup '\(message.subject ?? "-")' with \(message.attachmentIds.count) attachments") guard let identifier = message.identifier.stringId else { Logger.logVerbose("[GmailService] skipping this last backup?") diff --git a/FlowCrypt/Functionality/Services/Folders Services/RemoteFoldersProviderType/GmailService+folders.swift b/FlowCrypt/Functionality/Services/Folders Services/RemoteFoldersProviderType/GmailService+folders.swift index d91c488ef..a03456c60 100644 --- a/FlowCrypt/Functionality/Services/Folders Services/RemoteFoldersProviderType/GmailService+folders.swift +++ b/FlowCrypt/Functionality/Services/Folders Services/RemoteFoldersProviderType/GmailService+folders.swift @@ -32,7 +32,7 @@ extension GmailService: RemoteFoldersProviderType { // TODO: - TOM - Implement categories if needed let folders = labels - .compactMap { (label) -> GTLRGmail_Label? in + .compactMap { label -> GTLRGmail_Label? in guard let identifier = label.identifier, identifier.isNotEmpty else { logger.logInfo("skip label with \(label.identifier ?? "")") return nil diff --git a/FlowCrypt/Functionality/WKDURLs/WKDURLsCreator.swift b/FlowCrypt/Functionality/WKDURLs/WKDURLsCreator.swift new file mode 100644 index 000000000..c2b1f8490 --- /dev/null +++ b/FlowCrypt/Functionality/WKDURLs/WKDURLsCreator.swift @@ -0,0 +1,40 @@ +// +// WKDURLsConstructor.swift +// FlowCrypt +// +// Created by Yevhen Kyivskyi on 15.05.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation + +/// WKD - Web Key Directory, follow this link for more information https://wiki.gnupg.org/WKD + +enum WKDURLMode { + case direct + case advanced +} + +protocol WKDURLsConstructorType { + func construct(from email: String, mode: WKDURLMode) -> String? +} + +class WKDURLsConstructor: WKDURLsConstructorType { + + func construct(from email: String, mode: WKDURLMode) -> String? { + + let parts = email.split(separator: "@") + if parts.count != 2 { + return nil + } + let user = parts[0] + let recipientDomain = parts[1] + + let hu = String(user).data().zBase32EncodedString() + + let advancedURL = "https://openpgpkey.\(recipientDomain).well-known/openpgpkey/\(recipientDomain)/hu/\(hu)?l=\(user)" + let directURL = "https://\(recipientDomain)/.well-known/openpgpkey/hu/\(hu)?l=\(user)" + + return mode == .advanced ? advancedURL : directURL + } +} diff --git a/FlowCryptCommon/Extensions/Data/DataExntensions+ZBase32Encoding.swift b/FlowCryptCommon/Extensions/Data/DataExntensions+ZBase32Encoding.swift new file mode 100644 index 000000000..59ef733d8 --- /dev/null +++ b/FlowCryptCommon/Extensions/Data/DataExntensions+ZBase32Encoding.swift @@ -0,0 +1,158 @@ +// +// DataExntensions+Encoding.swift +// FlowCryptCommon +// +// Created by Yevhen Kyivskyi on 17.05.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import Foundation + +public extension Data { + + private enum Constants { + static let alphabet = "ybndrfg8ejkmcpqxot1uwisza345h769".unicodeScalars.map { UInt8(ascii: $0) } + static let bitsInZBase32Character = 5 + static let bitsInByte = 8 + } + + func zBase32EncodedString() -> String { + + let bytes = [UInt8](self) + let capacity = (bytes.count / Constants.bitsInZBase32Character) * Constants.bitsInZBase32Character + + var encoded: [UInt8] = [] + + encoded.reserveCapacity(capacity) + + var input = bytes.makeIterator() + while let firstByte = input.next() { + let secondByte = input.next() + let thirdByte = input.next() + let fourthByte = input.next() + let fifthByte = input.next() + + let firstChar = encode(firstByte: firstByte) + let secondChar = encode(firstByte: firstByte, secondByte: secondByte) + let thirdChar = encode(secondByte: secondByte) + let fourthChar = encode(secondByte: secondByte, thirdByte: thirdByte) + let fifthChar = encode(thirdByte: thirdByte, fourthByte: fourthByte) + let sixthChar = encode(fourthByte: fourthByte) + let seventhChar = encode(fourthByte: fourthByte, fifthByte: fifthByte) + let eightChar = encode(fifthByte: fifthByte) + + encoded.append(firstChar) + encoded.append(secondChar) + if let thirdChar = thirdChar { + encoded.append(thirdChar) + } + if let fourthChar = fourthChar { + encoded.append(fourthChar) + } + if let fifthChar = fifthChar { + encoded.append(fifthChar) + } + if let sixthChar = sixthChar { + encoded.append(sixthChar) + } + if let seventhChar = seventhChar { + encoded.append(seventhChar) + } + if let eightChar = eightChar { + encoded.append(eightChar) + } + } + + return String(decoding: encoded, as: Unicode.UTF8.self) + } + + private func encode(firstByte: UInt8) -> UInt8 { + // First: 00000 --- + let index = firstByte >> 3 + return Constants.alphabet[Int(index)] + } + + private func encode(firstByte: UInt8, secondByte: UInt8?) -> UInt8 { + // First: -----000 + var index = (firstByte & 0b00000111) << 2 + + if let secondByte = secondByte { + // Second: 00 ------ + index |= (secondByte & 0b11000000) >> 6 + } + + return Constants.alphabet[Int(index)] + } + + private func encode(secondByte: UInt8?) -> UInt8? { + guard let secondByte = secondByte else { + return nil + } + // Second: --00000- + let index = (secondByte & 0b00111110) >> 1 + return Constants.alphabet[Int(index)] + } + + private func encode(secondByte: UInt8?, thirdByte: UInt8?) -> UInt8? { + guard let secondByte = secondByte else { + return nil + } + // Second: -------0 + var index = (secondByte & 0b00000001) << 4 + + if let thirdByte = thirdByte { + // Third: 0000---- + index |= (thirdByte & 0b11110000) >> 4 + } + + return Constants.alphabet[Int(index)] + } + + private func encode(thirdByte: UInt8?, fourthByte: UInt8?) -> UInt8? { + guard let thirdByte = thirdByte else { + return nil + } + // Third:----0000 + var index = (thirdByte & 0b00001111) << 1 + + if let fourthByte = fourthByte { + // Fourth: 0------- + index |= (fourthByte & 0b10000000) >> 7 + } + + return Constants.alphabet[Int(index)] + } + + private func encode(fourthByte: UInt8?) -> UInt8? { + guard let fourthByte = fourthByte else { + return nil + } + // Fourth: -00000-- + let index = (fourthByte & 0b01111100) >> 2 + return Constants.alphabet[Int(index)] + } + + private func encode(fourthByte: UInt8?, fifthByte: UInt8?) -> UInt8? { + guard let fourthByte = fourthByte else { + return nil + } + // Fourth: ------00 + var index = (fourthByte & 0b00000011) << 3 + + if let fifthByte = fifthByte { + // Fifth: 000----- + index |= (fifthByte & 0b11100000) >> 5 + } + + return Constants.alphabet[Int(index)] + } + + private func encode(fifthByte: UInt8?) -> UInt8? { + guard let fifthByte = fifthByte else { + return nil + } + // // Fifth: ---00000 + let index = fifthByte & 0b00011111 + return Constants.alphabet[Int(index)] + } +} diff --git a/FlowCryptCommon/Extensions/DataExtensions.swift b/FlowCryptCommon/Extensions/Data/DataExtensions.swift similarity index 100% rename from FlowCryptCommon/Extensions/DataExtensions.swift rename to FlowCryptCommon/Extensions/Data/DataExtensions.swift diff --git a/FlowCryptTests/Functionallity/WKDURLs/WKDURLsConstructorTests.swift b/FlowCryptTests/Functionallity/WKDURLs/WKDURLsConstructorTests.swift new file mode 100644 index 000000000..dcfc4b431 --- /dev/null +++ b/FlowCryptTests/Functionallity/WKDURLs/WKDURLsConstructorTests.swift @@ -0,0 +1,59 @@ +// +// WKDURLsTests.swift +// FlowCryptTests +// +// Created by Yevhen Kyivskyi on 17.05.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import XCTest + +class WKDURLsTests: XCTestCase { + + var constructor: WKDURLsConstructorType! + + override func setUp() { + constructor = WKDURLsConstructor() + } + + override func tearDown() { + constructor = nil + } + + func test_direct_mode_construct_URL_success() { + let inputEmail = "example@mail.com" + let expectedURL = "https://mail.com/.well-known/openpgpkey/hu/cihgn5mopt1o?l=example" + + let constructedURL = constructor.construct(from: inputEmail, mode: .direct) + + XCTAssert(constructedURL == expectedURL) + } + + func test_advanced_mode_construct_URL_success() { + let inputEmail = "example@mail.com" + let expectedURL = "https://openpgpkey.mail.com.well-known/openpgpkey/mail.com/hu/cihgn5mopt1o?l=example" + + let constructedURL = constructor.construct(from: inputEmail, mode: .advanced) + + XCTAssert(constructedURL == expectedURL) + } + + func test_construct_URL_failure() { + var inputEmail = "examplemail.com" + var constructedURL = constructor.construct(from: inputEmail, mode: .advanced) + + XCTAssertNil(constructedURL) + + inputEmail = "example@" + + constructedURL = constructor.construct(from: inputEmail, mode: .advanced) + + XCTAssertNil(constructedURL) + + inputEmail = "@mail.com" + + constructedURL = constructor.construct(from: inputEmail, mode: .advanced) + + XCTAssertNil(constructedURL) + } +} diff --git a/FlowCryptTests/Functionallity/WKDURLs/ZBase32EncodingTests.swift b/FlowCryptTests/Functionallity/WKDURLs/ZBase32EncodingTests.swift new file mode 100644 index 000000000..f5a67c268 --- /dev/null +++ b/FlowCryptTests/Functionallity/WKDURLs/ZBase32EncodingTests.swift @@ -0,0 +1,19 @@ +// +// ZBase32EncodingTests.swift +// FlowCryptTests +// +// Created by Yevhen Kyivskyi on 17.05.2021. +// Copyright © 2021 FlowCrypt Limited. All rights reserved. +// + +import XCTest + +class ZBase32EncodingTests: XCTestCase { + + func testStringEncoding() throws { + let inputString = "example@email.com" + let encodedString = "cihgn5mopt1wy3mpcfwsamudp7so" + + XCTAssert(inputString.data().zBase32EncodedString() == encodedString) + } +} From fd6fc4be79e7385bc5f4454289e9542fa3ff85f6 Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Mon, 17 May 2021 16:35:00 +0300 Subject: [PATCH 2/4] Reverted changes made by XCode --- FlowCrypt/Controllers/Compose/ComposeViewController.swift | 6 +++--- FlowCrypt/Controllers/Inbox/InboxViewController.swift | 2 +- .../Mail Provider/Backup Provider/Gmail+Backup.swift | 2 +- .../RemoteFoldersProviderType/GmailService+folders.swift | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/FlowCrypt/Controllers/Compose/ComposeViewController.swift b/FlowCrypt/Controllers/Compose/ComposeViewController.swift index 17b80c2d1..300b06ad9 100644 --- a/FlowCrypt/Controllers/Compose/ComposeViewController.swift +++ b/FlowCrypt/Controllers/Compose/ComposeViewController.swift @@ -324,7 +324,7 @@ extension ComposeViewController { private func isInputValid() -> Bool { let emails = recipients.map(\.email) - let hasContent = emails.filter(\.hasContent) + let hasContent = emails.filter { $0.hasContent } guard emails.count == hasContent.count else { showAlert(message: "compose_enter_recipient".localized) @@ -468,7 +468,7 @@ extension ComposeViewController { .onShouldReturn { [weak self] textField -> Bool in self?.shouldReturn(with: textField) ?? true } - .onShouldChangeCharacters { [weak self] textField, character -> (Bool) in + .onShouldChangeCharacters { [weak self] (textField, character) -> (Bool) in self?.shouldChange(with: textField, and: character) ?? true } .then { @@ -584,7 +584,7 @@ extension ComposeViewController { guard textField.text == "" else { return } let selectedRecipients = recipients - .filter(\.state.isSelected) + .filter { $0.state.isSelected } guard selectedRecipients.isEmpty else { // remove selected recipients diff --git a/FlowCrypt/Controllers/Inbox/InboxViewController.swift b/FlowCrypt/Controllers/Inbox/InboxViewController.swift index 07cbb0de9..82c35a15f 100644 --- a/FlowCrypt/Controllers/Inbox/InboxViewController.swift +++ b/FlowCrypt/Controllers/Inbox/InboxViewController.swift @@ -214,7 +214,7 @@ extension InboxViewController { // insert new messages let indexesToInsert = messageContext.messages .enumerated() - .map { index, _ -> Int in + .map { (index, _) -> Int in let indexInTableView = index + count return indexInTableView } diff --git a/FlowCrypt/Functionality/Mail Provider/Backup Provider/Gmail+Backup.swift b/FlowCrypt/Functionality/Mail Provider/Backup Provider/Gmail+Backup.swift index 90d15d85b..753b04a16 100644 --- a/FlowCrypt/Functionality/Mail Provider/Backup Provider/Gmail+Backup.swift +++ b/FlowCrypt/Functionality/Mail Provider/Backup Provider/Gmail+Backup.swift @@ -24,7 +24,7 @@ extension GmailService: BackupProvider { Logger.logVerbose("[GmailService] searching done, found \(backupMessages.count) backup messages") let uniqueMessages = Set(backupMessages) let attachments = uniqueMessages - .compactMap { message -> [(String, String)]? in + .compactMap { (message) -> [(String, String)]? in Logger.logVerbose("[GmailService] processing backup '\(message.subject ?? "-")' with \(message.attachmentIds.count) attachments") guard let identifier = message.identifier.stringId else { Logger.logVerbose("[GmailService] skipping this last backup?") diff --git a/FlowCrypt/Functionality/Services/Folders Services/RemoteFoldersProviderType/GmailService+folders.swift b/FlowCrypt/Functionality/Services/Folders Services/RemoteFoldersProviderType/GmailService+folders.swift index a03456c60..d91c488ef 100644 --- a/FlowCrypt/Functionality/Services/Folders Services/RemoteFoldersProviderType/GmailService+folders.swift +++ b/FlowCrypt/Functionality/Services/Folders Services/RemoteFoldersProviderType/GmailService+folders.swift @@ -32,7 +32,7 @@ extension GmailService: RemoteFoldersProviderType { // TODO: - TOM - Implement categories if needed let folders = labels - .compactMap { label -> GTLRGmail_Label? in + .compactMap { (label) -> GTLRGmail_Label? in guard let identifier = label.identifier, identifier.isNotEmpty else { logger.logInfo("skip label with \(label.identifier ?? "")") return nil From cae691200551f053d83f97e1e7c9e2d8d533280d Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Mon, 17 May 2021 23:25:12 +0300 Subject: [PATCH 3/4] Fixed encryption and encoding flow; Added requested test cases; --- FlowCrypt.xcodeproj/project.pbxproj | 16 ++++++---- ...Creator.swift => WKDURLsConstructor.swift} | 12 ++++---- .../DataExntensions+ZBase32Encoding.swift | 4 +-- .../WKDURLs/WKDURLsConstructorTests.swift | 30 +++++++++++++++---- .../WKDURLs/ZBase32EncodingTests.swift | 13 +++++++- 5 files changed, 53 insertions(+), 22 deletions(-) rename FlowCrypt/Functionality/WKDURLs/{WKDURLsCreator.swift => WKDURLsConstructor.swift} (75%) diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index 22aa1d338..2690e7c2d 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -10,11 +10,12 @@ 04B4728D1ECE29D200B8266F /* KeyInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B4728B1ECE29D200B8266F /* KeyInfo.swift */; }; 04B472951ECE29F600B8266F /* MyMenuViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472921ECE29F600B8266F /* MyMenuViewController.swift */; }; 04B472961ECE29F600B8266F /* SideMenuNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04B472931ECE29F600B8266F /* SideMenuNavigationController.swift */; }; - 21CE25E62650070300ADFF4B /* WKDURLsCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21CE25E52650070300ADFF4B /* WKDURLsCreator.swift */; }; - 21F836A02652A19A00B2448C /* WKDURLsCreator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21CE25E52650070300ADFF4B /* WKDURLsCreator.swift */; }; + 21CE25E62650070300ADFF4B /* WKDURLsConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21CE25E52650070300ADFF4B /* WKDURLsConstructor.swift */; }; + 21F836A02652A19A00B2448C /* WKDURLsConstructor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21CE25E52650070300ADFF4B /* WKDURLsConstructor.swift */; }; 21F836B62652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F836B52652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift */; }; 21F836CC2652A38700B2448C /* ZBase32EncodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F836CB2652A38700B2448C /* ZBase32EncodingTests.swift */; }; 21F836D32652A46E00B2448C /* WKDURLsConstructorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F836D22652A46E00B2448C /* WKDURLsConstructorTests.swift */; }; + 21F836E92652C76800B2448C /* NOTICE.md in Resources */ = {isa = PBXBuildFile; fileRef = 21F836E82652C76800B2448C /* NOTICE.md */; }; 32DCA00224982EDA88D69C6E /* AppErr.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DCA4B11D4531B3B04D01D1 /* AppErr.swift */; }; 32DCA04CA0DAB79C39514782 /* CoreTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DCAC732B988D9704658812 /* CoreTypes.swift */; }; 32DCA1414EEA727B86C337D5 /* Core.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DCA0C3D34A69851A238E87 /* Core.swift */; }; @@ -350,10 +351,11 @@ 069059B887A8580765029BF9 /* Pods_FlowCrypt.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FlowCrypt.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 113F04B20ECC35FC59A81A6C /* Pods-FlowCryptTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptTests.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptTests/Pods-FlowCryptTests.release.xcconfig"; sourceTree = ""; }; 11C1375F41411882DC4C9431 /* Pods-FlowCryptUIApplication.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptUIApplication.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptUIApplication/Pods-FlowCryptUIApplication.release.xcconfig"; sourceTree = ""; }; - 21CE25E52650070300ADFF4B /* WKDURLsCreator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKDURLsCreator.swift; sourceTree = ""; }; + 21CE25E52650070300ADFF4B /* WKDURLsConstructor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKDURLsConstructor.swift; sourceTree = ""; }; 21F836B52652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataExntensions+ZBase32Encoding.swift"; sourceTree = ""; }; 21F836CB2652A38700B2448C /* ZBase32EncodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZBase32EncodingTests.swift; sourceTree = ""; }; 21F836D22652A46E00B2448C /* WKDURLsConstructorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKDURLsConstructorTests.swift; sourceTree = ""; }; + 21F836E82652C76800B2448C /* NOTICE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = NOTICE.md; sourceTree = ""; }; 27D857C43583281B45F427F8 /* Pods-FlowCryptUI.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptUI.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptUI/Pods-FlowCryptUI.release.xcconfig"; sourceTree = ""; }; 32DCA058652FD4616FB04FB6 /* SequenceExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SequenceExtensions.swift; sourceTree = ""; }; 32DCA0C3D34A69851A238E87 /* Core.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Core.swift; sourceTree = ""; }; @@ -724,7 +726,7 @@ 21CE25D32650034500ADFF4B /* WKDURLs */ = { isa = PBXGroup; children = ( - 21CE25E52650070300ADFF4B /* WKDURLsCreator.swift */, + 21CE25E52650070300ADFF4B /* WKDURLsConstructor.swift */, ); path = WKDURLs; sourceTree = ""; @@ -1314,6 +1316,7 @@ C132B9BA1EC2DBD800763715 /* Assets.xcassets */, 949ED9412303E3B400530579 /* Colors.xcassets */, C132B9BF1EC2DBD800763715 /* Info.plist */, + 21F836E82652C76800B2448C /* NOTICE.md */, ); path = FlowCrypt; sourceTree = ""; @@ -1934,6 +1937,7 @@ 9F716308234FC73E0031645E /* Localizable.strings in Resources */, D2F6D13E2434FF1400DB4065 /* providers.json in Resources */, 32DCA6A3C9D59DD16B136772 /* flowcrypt-ios-prod.js.txt in Resources */, + 21F836E92652C76800B2448C /* NOTICE.md in Resources */, A33BAA8422EA4B4F00CC1B5C /* flowcrypt-ios-icon.png in Resources */, 949ED9422303E3B400530579 /* Colors.xcassets in Resources */, ); @@ -2262,7 +2266,7 @@ 5A39F439239ECDD0001F4607 /* ExtensionTests.swift in Sources */, D212D36524C1AC4800035991 /* KeyId.swift in Sources */, 9F003DBC25EA92D000EB38C0 /* LogOutHandler.swift in Sources */, - 21F836A02652A19A00B2448C /* WKDURLsCreator.swift in Sources */, + 21F836A02652A19A00B2448C /* WKDURLsConstructor.swift in Sources */, 9F7DE8C5232029BD00F10B3E /* Core.swift in Sources */, 32DCAD6360C9EFF4FDD8EF6F /* DispatchTimeExtension.swift in Sources */, 9F7DE8C723202A0200F10B3E /* CoreHost.swift in Sources */, @@ -2295,7 +2299,7 @@ D20D3C752520AB9A00D4AA9A /* BackupService.swift in Sources */, C192421F1EC48B6900C3D251 /* SetupViewController.swift in Sources */, 9F0C3C2623194E0A00299985 /* FolderViewModel.swift in Sources */, - 21CE25E62650070300ADFF4B /* WKDURLsCreator.swift in Sources */, + 21CE25E62650070300ADFF4B /* WKDURLsConstructor.swift in Sources */, 9FC411212595EA12001180A8 /* MessageSearchProvider.swift in Sources */, D27B911D24EFE806002DF0A1 /* ContactObject.swift in Sources */, 9FDF3654235A218E00614596 /* main.swift in Sources */, diff --git a/FlowCrypt/Functionality/WKDURLs/WKDURLsCreator.swift b/FlowCrypt/Functionality/WKDURLs/WKDURLsConstructor.swift similarity index 75% rename from FlowCrypt/Functionality/WKDURLs/WKDURLsCreator.swift rename to FlowCrypt/Functionality/WKDURLs/WKDURLsConstructor.swift index c2b1f8490..120a85fa6 100644 --- a/FlowCrypt/Functionality/WKDURLs/WKDURLsCreator.swift +++ b/FlowCrypt/Functionality/WKDURLs/WKDURLsConstructor.swift @@ -6,6 +6,7 @@ // Copyright © 2021 FlowCrypt Limited. All rights reserved. // +import CryptoKit import Foundation /// WKD - Web Key Directory, follow this link for more information https://wiki.gnupg.org/WKD @@ -22,18 +23,15 @@ protocol WKDURLsConstructorType { class WKDURLsConstructor: WKDURLsConstructorType { func construct(from email: String, mode: WKDURLMode) -> String? { - let parts = email.split(separator: "@") if parts.count != 2 { return nil } - let user = parts[0] - let recipientDomain = parts[1] - - let hu = String(user).data().zBase32EncodedString() - - let advancedURL = "https://openpgpkey.\(recipientDomain).well-known/openpgpkey/\(recipientDomain)/hu/\(hu)?l=\(user)" + let user = String(parts[0]) + let recipientDomain = String(parts[1]).lowercased() + let hu = String(decoding: user.lowercased().data().SHA1.zBase32EncodedBytes(), as: Unicode.UTF8.self) let directURL = "https://\(recipientDomain)/.well-known/openpgpkey/hu/\(hu)?l=\(user)" + let advancedURL = "https://openpgpkey.\(recipientDomain)/.well-known/openpgpkey/\(recipientDomain)/hu/\(hu)?l=\(user)" return mode == .advanced ? advancedURL : directURL } diff --git a/FlowCryptCommon/Extensions/Data/DataExntensions+ZBase32Encoding.swift b/FlowCryptCommon/Extensions/Data/DataExntensions+ZBase32Encoding.swift index 59ef733d8..5fe3cdae8 100644 --- a/FlowCryptCommon/Extensions/Data/DataExntensions+ZBase32Encoding.swift +++ b/FlowCryptCommon/Extensions/Data/DataExntensions+ZBase32Encoding.swift @@ -16,7 +16,7 @@ public extension Data { static let bitsInByte = 8 } - func zBase32EncodedString() -> String { + func zBase32EncodedBytes() -> [UInt8] { let bytes = [UInt8](self) let capacity = (bytes.count / Constants.bitsInZBase32Character) * Constants.bitsInZBase32Character @@ -63,7 +63,7 @@ public extension Data { } } - return String(decoding: encoded, as: Unicode.UTF8.self) + return encoded } private func encode(firstByte: UInt8) -> UInt8 { diff --git a/FlowCryptTests/Functionallity/WKDURLs/WKDURLsConstructorTests.swift b/FlowCryptTests/Functionallity/WKDURLs/WKDURLsConstructorTests.swift index dcfc4b431..ec20e582a 100644 --- a/FlowCryptTests/Functionallity/WKDURLs/WKDURLsConstructorTests.swift +++ b/FlowCryptTests/Functionallity/WKDURLs/WKDURLsConstructorTests.swift @@ -20,18 +20,36 @@ class WKDURLsTests: XCTestCase { constructor = nil } - func test_direct_mode_construct_URL_success() { - let inputEmail = "example@mail.com" - let expectedURL = "https://mail.com/.well-known/openpgpkey/hu/cihgn5mopt1o?l=example" + func test_direct_mode_lowercased_construct_URL_success() { + let inputEmail = "recipient.hello@example.com" + let expectedURL = "https://example.com/.well-known/openpgpkey/hu/1sbjrcaf8m3zckmmuej93nx61yn1sttg?l=recipient.hello" let constructedURL = constructor.construct(from: inputEmail, mode: .direct) XCTAssert(constructedURL == expectedURL) } - func test_advanced_mode_construct_URL_success() { - let inputEmail = "example@mail.com" - let expectedURL = "https://openpgpkey.mail.com.well-known/openpgpkey/mail.com/hu/cihgn5mopt1o?l=example" + func test_advanced_mode_lowercased_construct_URL_success() { + let inputEmail = "recipient.hello@example.com" + let expectedURL = "https://openpgpkey.example.com/.well-known/openpgpkey/example.com/hu/1sbjrcaf8m3zckmmuej93nx61yn1sttg?l=recipient.hello" + + let constructedURL = constructor.construct(from: inputEmail, mode: .advanced) + + XCTAssert(constructedURL == expectedURL) + } + + func test_direct_mode_uppercased_construct_URL_success() { + let inputEmail = "UPPER@EXAMPLE.COM" + let expectedURL = "https://example.com/.well-known/openpgpkey/hu/awhcnhf7a4ax8qha5u1rwymkfaswmjz8?l=UPPER" + + let constructedURL = constructor.construct(from: inputEmail, mode: .direct) + + XCTAssert(constructedURL == expectedURL) + } + + func test_advanced_mode_uppercased_construct_URL_success() { + let inputEmail = "UPPER@EXAMPLE.COM" + let expectedURL = "https://openpgpkey.example.com/.well-known/openpgpkey/example.com/hu/awhcnhf7a4ax8qha5u1rwymkfaswmjz8?l=UPPER" let constructedURL = constructor.construct(from: inputEmail, mode: .advanced) diff --git a/FlowCryptTests/Functionallity/WKDURLs/ZBase32EncodingTests.swift b/FlowCryptTests/Functionallity/WKDURLs/ZBase32EncodingTests.swift index f5a67c268..8c35f4510 100644 --- a/FlowCryptTests/Functionallity/WKDURLs/ZBase32EncodingTests.swift +++ b/FlowCryptTests/Functionallity/WKDURLs/ZBase32EncodingTests.swift @@ -14,6 +14,17 @@ class ZBase32EncodingTests: XCTestCase { let inputString = "example@email.com" let encodedString = "cihgn5mopt1wy3mpcfwsamudp7so" - XCTAssert(inputString.data().zBase32EncodedString() == encodedString) + XCTAssert( + String(decoding: inputString.data().zBase32EncodedBytes(), as: Unicode.UTF8.self) == encodedString + ) + } + + func testEncryptedStringEncoding() throws { + let inputString = "example@email.com" + let encodedString = "8dkp15twcw7feu1i8em784qtw91y3cs7" + print(String(decoding: inputString.data().SHA1.zBase32EncodedBytes(), as: Unicode.UTF8.self)) + XCTAssert( + String(decoding: inputString.data().SHA1.zBase32EncodedBytes(), as: Unicode.UTF8.self) == encodedString + ) } } From 715072e1278e5605e3bd77ec788a260d5740cbe1 Mon Sep 17 00:00:00 2001 From: ykyivskyi-gd Date: Tue, 18 May 2021 00:05:11 +0300 Subject: [PATCH 4/4] Removed unused file; --- FlowCrypt.xcodeproj/project.pbxproj | 4 ---- 1 file changed, 4 deletions(-) diff --git a/FlowCrypt.xcodeproj/project.pbxproj b/FlowCrypt.xcodeproj/project.pbxproj index 2690e7c2d..6921554ba 100644 --- a/FlowCrypt.xcodeproj/project.pbxproj +++ b/FlowCrypt.xcodeproj/project.pbxproj @@ -15,7 +15,6 @@ 21F836B62652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F836B52652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift */; }; 21F836CC2652A38700B2448C /* ZBase32EncodingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F836CB2652A38700B2448C /* ZBase32EncodingTests.swift */; }; 21F836D32652A46E00B2448C /* WKDURLsConstructorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 21F836D22652A46E00B2448C /* WKDURLsConstructorTests.swift */; }; - 21F836E92652C76800B2448C /* NOTICE.md in Resources */ = {isa = PBXBuildFile; fileRef = 21F836E82652C76800B2448C /* NOTICE.md */; }; 32DCA00224982EDA88D69C6E /* AppErr.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DCA4B11D4531B3B04D01D1 /* AppErr.swift */; }; 32DCA04CA0DAB79C39514782 /* CoreTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DCAC732B988D9704658812 /* CoreTypes.swift */; }; 32DCA1414EEA727B86C337D5 /* Core.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32DCA0C3D34A69851A238E87 /* Core.swift */; }; @@ -355,7 +354,6 @@ 21F836B52652A26B00B2448C /* DataExntensions+ZBase32Encoding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "DataExntensions+ZBase32Encoding.swift"; sourceTree = ""; }; 21F836CB2652A38700B2448C /* ZBase32EncodingTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZBase32EncodingTests.swift; sourceTree = ""; }; 21F836D22652A46E00B2448C /* WKDURLsConstructorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WKDURLsConstructorTests.swift; sourceTree = ""; }; - 21F836E82652C76800B2448C /* NOTICE.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = NOTICE.md; sourceTree = ""; }; 27D857C43583281B45F427F8 /* Pods-FlowCryptUI.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FlowCryptUI.release.xcconfig"; path = "Target Support Files/Pods-FlowCryptUI/Pods-FlowCryptUI.release.xcconfig"; sourceTree = ""; }; 32DCA058652FD4616FB04FB6 /* SequenceExtensions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SequenceExtensions.swift; sourceTree = ""; }; 32DCA0C3D34A69851A238E87 /* Core.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Core.swift; sourceTree = ""; }; @@ -1316,7 +1314,6 @@ C132B9BA1EC2DBD800763715 /* Assets.xcassets */, 949ED9412303E3B400530579 /* Colors.xcassets */, C132B9BF1EC2DBD800763715 /* Info.plist */, - 21F836E82652C76800B2448C /* NOTICE.md */, ); path = FlowCrypt; sourceTree = ""; @@ -1937,7 +1934,6 @@ 9F716308234FC73E0031645E /* Localizable.strings in Resources */, D2F6D13E2434FF1400DB4065 /* providers.json in Resources */, 32DCA6A3C9D59DD16B136772 /* flowcrypt-ios-prod.js.txt in Resources */, - 21F836E92652C76800B2448C /* NOTICE.md in Resources */, A33BAA8422EA4B4F00CC1B5C /* flowcrypt-ios-icon.png in Resources */, 949ED9422303E3B400530579 /* Colors.xcassets in Resources */, );