diff --git a/Signal/src/ViewControllers/NewContactThreadViewController.m b/Signal/src/ViewControllers/NewContactThreadViewController.m index 803f6832e..a06689d06 100644 --- a/Signal/src/ViewControllers/NewContactThreadViewController.m +++ b/Signal/src/ViewControllers/NewContactThreadViewController.m @@ -18,6 +18,7 @@ #import #import #import +#import #import NS_ASSUME_NONNULL_BEGIN @@ -394,18 +395,28 @@ NS_ASSUME_NONNULL_BEGIN BOOL hasSearchText = self.searchText.length > 0; if (hasSearchText) { - // Loki: // ======== - OWSTableSection *newConversationSection = [OWSTableSection new]; - [newConversationSection - addItem:[OWSTableItem disclosureItemWithText:NSLocalizedString(@"Start a Conversation", @"") - accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"start_conversation") - customRowHeight:UITableViewAutomaticDimension - actionBlock:^{ NSLog(@"Start a Conversation"); }]]; - [contents addSection:newConversationSection]; + NSString *publicKey = self.searchBar.text; + BOOL isValid = [ECKeyPair isValidHexEncodedPublicKeyWithCandidate:publicKey]; + if (!isValid) { + OWSTableSection *invalidPublicKeySection = [OWSTableSection new]; + [invalidPublicKeySection + addItem:[OWSTableItem softCenterLabelItemWithText:NSLocalizedString(@"Invalid public key", @"") + customRowHeight:UITableViewAutomaticDimension]]; + [contents addSection:invalidPublicKeySection]; + } else { + OWSTableSection *newConversationSection = [OWSTableSection new]; + [newConversationSection + addItem:[OWSTableItem disclosureItemWithText:NSLocalizedString(@"Start a Conversation", @"") + accessibilityIdentifier:ACCESSIBILITY_IDENTIFIER_WITH_NAME(self, @"start_conversation") + customRowHeight:UITableViewAutomaticDimension + actionBlock:^{ + [weakSelf newConversationWithRecipientId:publicKey]; + }]]; + [contents addSection:newConversationSection]; + } // ======== - for (OWSTableSection *section in [self contactsSectionsForSearch]) { [contents addSection:section]; } @@ -723,13 +734,18 @@ NS_ASSUME_NONNULL_BEGIN [sections addObject:inviteeSection]; } + // Loki: + // ======== + NSString *publicKey = self.searchBar.text; + BOOL isValidPublicKey = [ECKeyPair isValidHexEncodedPublicKeyWithCandidate:publicKey]; + // ======== - if (!hasSearchResults) { + if (isValidPublicKey && !hasSearchResults) { // No Search Results OWSTableSection *noResultsSection = [OWSTableSection new]; [noResultsSection addItem:[OWSTableItem softCenterLabelItemWithText: - NSLocalizedString(@"SETTINGS_BLOCK_LIST_NO_SEARCH_RESULTS", + NSLocalizedString(@"No search results", @"A label that indicates the user's search has no matching results.") customRowHeight:UITableViewAutomaticDimension]]; diff --git a/Signal/src/ViewControllers/Registration/OnboardingKeyPairViewController.swift b/Signal/src/ViewControllers/Registration/OnboardingKeyPairViewController.swift index 48b64a5e3..8a515ef74 100644 --- a/Signal/src/ViewControllers/Registration/OnboardingKeyPairViewController.swift +++ b/Signal/src/ViewControllers/Registration/OnboardingKeyPairViewController.swift @@ -1,3 +1,4 @@ + final class OnboardingKeyPairViewController : OnboardingBaseViewController { private var mode: Mode = .register { didSet { if mode != oldValue { handleModeChanged() } } } private var keyPair: ECKeyPair! { didSet { updateMnemonic() } } @@ -199,7 +200,9 @@ final class OnboardingKeyPairViewController : OnboardingBaseViewController { do { let hexEncodedPrivateKey = try Mnemonic.decode(mnemonic: mnemonic) let keyPair = ECKeyPair.generate(withHexEncodedPrivateKey: hexEncodedPrivateKey) + // Use KVC to access dbConnection even though it's private let databaseConnection = OWSIdentityManager.shared().value(forKey: "dbConnection") as! YapDatabaseConnection + // OWSPrimaryStorageIdentityKeyStoreIdentityKey is private so just use its value directly databaseConnection.setObject(keyPair, forKey: "TSStorageManagerIdentityKeyStoreIdentityKey", inCollection: OWSPrimaryStorageIdentityKeyStoreCollection) hexEncodedPublicKey = keyPair.hexEncodedPublicKey } catch let error { diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index dc3a312f6..d64cbf1bf 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -2566,3 +2566,5 @@ "Your mnemonic couldn't be verified. Please check what you entered and try again." = "Your mnemonic couldn't be verified. Please check what you entered and try again."; "Search by name or public key" = "Search by name or public key"; "Start a Conversation" = "Start a Conversation"; +"Invalid public key" = "Invalid public key"; +"No search results" = "No search results"; diff --git a/SignalMessaging/contacts/SystemContactsFetcher.swift b/SignalMessaging/contacts/SystemContactsFetcher.swift index 32a6bbb4c..ef4d6d22d 100644 --- a/SignalMessaging/contacts/SystemContactsFetcher.swift +++ b/SignalMessaging/contacts/SystemContactsFetcher.swift @@ -232,7 +232,6 @@ public class SystemContactsFetcher: NSObject { switch authorizationStatus { case .notDetermined: return completion(nil) - // Loki: Original code // ======== // if CurrentAppContext().isInBackground() { diff --git a/SignalServiceKit/src/Loki/ECKeyPair.m b/SignalServiceKit/src/Loki/ECKeyPair.m index ab88812cc..bbf77f769 100644 --- a/SignalServiceKit/src/Loki/ECKeyPair.m +++ b/SignalServiceKit/src/Loki/ECKeyPair.m @@ -1,5 +1,4 @@ #import "ECKeyPair.h" -#import extern void curve25519_donna(unsigned char *output, const unsigned char *a, const unsigned char *b); @@ -19,6 +18,7 @@ extern void curve25519_donna(unsigned char *output, const unsigned char *a, cons NSMutableData *publicKey = [NSMutableData dataWithLength:ECCKeyLength]; if (!publicKey) { OWSFail(@"Could not allocate buffer"); } curve25519_donna(publicKey.mutableBytes, privateKey.mutableBytes, basepoint); + // Use KVC to access privateKey and publicKey even though they're private ECKeyPair *result = [ECKeyPair new]; [result setValue:[privateKey copy] forKey:@"privateKey"]; [result setValue:[publicKey copy] forKey:@"publicKey"]; diff --git a/SignalServiceKit/src/Loki/ECKeyPair.swift b/SignalServiceKit/src/Loki/ECKeyPair.swift index 4fd48b16d..a2581a5e5 100644 --- a/SignalServiceKit/src/Loki/ECKeyPair.swift +++ b/SignalServiceKit/src/Loki/ECKeyPair.swift @@ -6,6 +6,17 @@ public extension ECKeyPair { } var hexEncodedPublicKey: String { + // Prefixing with "05" is necessary for what seems to be a sort of Signal public key versioning system return "05" + publicKey.map { String(format: "%02hhx", $0) }.joined() } + + @objc public static func isValidHexEncodedPublicKey(candidate: String) -> Bool { + // Check that it's a valid hexadecimal encoding + let allowedCharacters = CharacterSet(charactersIn: "0123456789ABCDEF") + guard candidate.uppercased().unicodeScalars.allSatisfy({ allowedCharacters.contains($0) }) else { return false } + // Check that it has either length 33 and a leading "05" or length 32 + guard (candidate.count == 33 && candidate.hasPrefix("05")) || candidate.count == 32 else { return false } + // It appears to be a valid public key + return true + } }