diff --git a/Pods b/Pods index c0cb51a84..50944b1cf 160000 --- a/Pods +++ b/Pods @@ -1 +1 @@ -Subproject commit c0cb51a84026b3e9e006d576a1c4ad936fc85c62 +Subproject commit 50944b1cfaf767af49574dc1d5004a3034840b95 diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index e5eb66c71..e51a4d6f2 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -558,8 +558,8 @@ B6FE7EB71ADD62FA00A6D22F /* PushKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B6FE7EB61ADD62FA00A6D22F /* PushKit.framework */; }; B8162F0322891AD600D46544 /* FriendRequestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8162F0222891AD600D46544 /* FriendRequestView.swift */; }; B8162F0522892C5F00D46544 /* FriendRequestViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8162F0422892C5F00D46544 /* FriendRequestViewDelegate.swift */; }; - B821F2F82272CED3002C88C0 /* OnboardingAccountDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B821F2F72272CED3002C88C0 /* OnboardingAccountDetailsViewController.swift */; }; - B821F2FA2272CEEE002C88C0 /* OnboardingKeyPairViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B821F2F92272CEEE002C88C0 /* OnboardingKeyPairViewController.swift */; }; + B821F2F82272CED3002C88C0 /* AccountDetailsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B821F2F72272CED3002C88C0 /* AccountDetailsViewController.swift */; }; + B821F2FA2272CEEE002C88C0 /* SeedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B821F2F92272CEEE002C88C0 /* SeedViewController.swift */; }; B846365B22B7418B00AF1514 /* Identicon+ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */; }; B89841E322B7579F00B1BDC6 /* NewConversationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B89841E222B7579F00B1BDC6 /* NewConversationViewController.swift */; }; B90418E6183E9DD40038554A /* DateUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = B90418E5183E9DD40038554A /* DateUtil.m */; }; @@ -1347,8 +1347,8 @@ B6FE7EB61ADD62FA00A6D22F /* PushKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PushKit.framework; path = System/Library/Frameworks/PushKit.framework; sourceTree = SDKROOT; }; B8162F0222891AD600D46544 /* FriendRequestView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendRequestView.swift; sourceTree = ""; }; B8162F0422892C5F00D46544 /* FriendRequestViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FriendRequestViewDelegate.swift; sourceTree = ""; }; - B821F2F72272CED3002C88C0 /* OnboardingAccountDetailsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingAccountDetailsViewController.swift; sourceTree = ""; }; - B821F2F92272CEEE002C88C0 /* OnboardingKeyPairViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingKeyPairViewController.swift; sourceTree = ""; }; + B821F2F72272CED3002C88C0 /* AccountDetailsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountDetailsViewController.swift; sourceTree = ""; }; + B821F2F92272CEEE002C88C0 /* SeedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeedViewController.swift; sourceTree = ""; }; B846365A22B7418B00AF1514 /* Identicon+ObjC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Identicon+ObjC.swift"; sourceTree = ""; }; B89841E222B7579F00B1BDC6 /* NewConversationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewConversationViewController.swift; sourceTree = ""; }; B90418E4183E9DD40038554A /* DateUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DateUtil.h; sourceTree = ""; }; @@ -2609,8 +2609,8 @@ B8162F0222891AD600D46544 /* FriendRequestView.swift */, B8162F0422892C5F00D46544 /* FriendRequestViewDelegate.swift */, B89841E222B7579F00B1BDC6 /* NewConversationViewController.swift */, - B821F2F72272CED3002C88C0 /* OnboardingAccountDetailsViewController.swift */, - B821F2F92272CEEE002C88C0 /* OnboardingKeyPairViewController.swift */, + B821F2F72272CED3002C88C0 /* AccountDetailsViewController.swift */, + B821F2F92272CEEE002C88C0 /* SeedViewController.swift */, 24A830A12293CD0100F4CAC0 /* LokiP2PServer.swift */, ); path = Loki; @@ -3703,7 +3703,7 @@ 4C21D5D8223AC60F00EF8A77 /* PhotoCapture.swift in Sources */, 4C13C9F620E57BA30089A98B /* ColorPickerViewController.swift in Sources */, B8162F0522892C5F00D46544 /* FriendRequestViewDelegate.swift in Sources */, - B821F2FA2272CEEE002C88C0 /* OnboardingKeyPairViewController.swift in Sources */, + B821F2FA2272CEEE002C88C0 /* SeedViewController.swift in Sources */, 4CC1ECFB211A553000CC13BE /* AppUpdateNag.swift in Sources */, 3448E16022134C89004B052E /* OnboardingSplashViewController.swift in Sources */, 34B6A903218B3F63007C4606 /* TypingIndicatorView.swift in Sources */, @@ -3721,7 +3721,7 @@ 45F32C222057297A00A300D5 /* MediaDetailViewController.m in Sources */, 34B3F8851E8DF1700035BE1A /* NewGroupViewController.m in Sources */, 34ABC0E421DD20C500ED9469 /* ConversationMessageMapping.swift in Sources */, - B821F2F82272CED3002C88C0 /* OnboardingAccountDetailsViewController.swift in Sources */, + B821F2F82272CED3002C88C0 /* AccountDetailsViewController.swift in Sources */, 34D8C0271ED3673300188D7C /* DebugUIMessages.m in Sources */, 34DBF003206BD5A500025978 /* OWSMessageTextView.m in Sources */, 34D1F0B41F86D31D0066283D /* ConversationCollectionView.m in Sources */, diff --git a/Signal/src/Loki/OnboardingAccountDetailsViewController.swift b/Signal/src/Loki/AccountDetailsViewController.swift similarity index 97% rename from Signal/src/Loki/OnboardingAccountDetailsViewController.swift rename to Signal/src/Loki/AccountDetailsViewController.swift index a6b3546cf..709461272 100644 --- a/Signal/src/Loki/OnboardingAccountDetailsViewController.swift +++ b/Signal/src/Loki/AccountDetailsViewController.swift @@ -1,5 +1,5 @@ -final class OnboardingAccountDetailsViewController : OnboardingBaseViewController { +final class AccountDetailsViewController : OnboardingBaseViewController { private lazy var userNameTextField: UITextField = { let result = UITextField() diff --git a/Signal/src/Loki/OnboardingKeyPairViewController.swift b/Signal/src/Loki/SeedViewController.swift similarity index 87% rename from Signal/src/Loki/OnboardingKeyPairViewController.swift rename to Signal/src/Loki/SeedViewController.swift index 7aa311baf..57f51e579 100644 --- a/Signal/src/Loki/OnboardingKeyPairViewController.swift +++ b/Signal/src/Loki/SeedViewController.swift @@ -1,7 +1,7 @@ -final class OnboardingKeyPairViewController : OnboardingBaseViewController { +final class SeedViewController : OnboardingBaseViewController { private var mode: Mode = .register { didSet { if mode != oldValue { handleModeChanged() } } } - private var keyPair: ECKeyPair! { didSet { updateMnemonic() } } + private var seed: Data! { didSet { updateMnemonic() } } private var mnemonic: String! { didSet { handleMnemonicChanged() } } private var userName: String? @@ -104,7 +104,7 @@ final class OnboardingKeyPairViewController : OnboardingBaseViewController { super.loadView() setUpViewHierarchy() handleModeChanged() // Perform initial update - updateKeyPair() + updateSeed() } private func setUpViewHierarchy() { @@ -159,14 +159,13 @@ final class OnboardingKeyPairViewController : OnboardingBaseViewController { if mode == .register { mnemonicTextField.resignFirstResponder() } } - private func updateKeyPair() { - let identityManager = OWSIdentityManager.shared() - identityManager.generateNewIdentityKey() // Generate and store a new identity key pair - keyPair = identityManager.identityKeyPair()! + private func updateSeed() { + seed = Randomness.generateRandomBytes(16) } private func updateMnemonic() { - mnemonic = Mnemonic.encode(hexEncodedString: keyPair.hexEncodedPrivateKey) + let hexEncodedSeed = seed!.toHexString() + mnemonic = Mnemonic.encode(hexEncodedString: hexEncodedSeed) } private func handleMnemonicChanged() { @@ -191,25 +190,27 @@ final class OnboardingKeyPairViewController : OnboardingBaseViewController { } @objc private func registerOrRestore() { - let hexEncodedPublicKey: String + var seed: Data switch mode { - case .register: hexEncodedPublicKey = keyPair.hexEncodedPublicKey + case .register: seed = self.seed case .restore: let mnemonic = mnemonicTextField.text! 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 + let hexEncodedSeed = try Mnemonic.decode(mnemonic: mnemonic) + seed = Data(hex: hexEncodedSeed) } catch let error { let error = error as? Mnemonic.DecodingError ?? Mnemonic.DecodingError.generic - errorLabel.text = error.errorDescription - return + return errorLabel.text = error.errorDescription } } + // Use KVC to access dbConnection even though it's private + let databaseConnection = OWSIdentityManager.shared().value(forKey: "dbConnection") as! YapDatabaseConnection + databaseConnection.setObject(seed.toHexString(), forKey: "LKLokiSeed", inCollection: OWSPrimaryStorageIdentityKeyStoreCollection) + if seed.count == 16 { seed = seed + seed } + let identityManager = OWSIdentityManager.shared() + identityManager.generateNewIdentityKeyPair(fromSeed: seed) // This also stores it + let keyPair = identityManager.identityKeyPair()! + let hexEncodedPublicKey = keyPair.hexEncodedPublicKey let accountManager = TSAccountManager.sharedInstance() accountManager.phoneNumberAwaitingVerification = hexEncodedPublicKey accountManager.didRegister() diff --git a/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m b/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m index f583f3833..7ceab1e1c 100644 --- a/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m +++ b/Signal/src/ViewControllers/AppSettings/AppSettingsViewController.m @@ -520,8 +520,11 @@ - (void)showSeed { NSString *title = NSLocalizedString(@"Your Seed", @""); - ECKeyPair *keyPair = OWSIdentityManager.sharedManager.identityKeyPair; - NSString *mnemonic = [LKMnemonic encodeHexEncodedString:keyPair.hexEncodedPrivateKey]; + OWSIdentityManager *identityManager = OWSIdentityManager.sharedManager; + YapDatabaseConnection *databaseConnection = (YapDatabaseConnection *)[identityManager valueForKey:@"dbConnection"]; + NSString *hexEncodedSeed = [databaseConnection objectForKey:@"LKLokiSeed" inCollection:OWSPrimaryStorageIdentityKeyStoreCollection]; + if (hexEncodedSeed == nil) { hexEncodedSeed = identityManager.identityKeyPair.hexEncodedPrivateKey; } // Legacy account + NSString *mnemonic = [LKMnemonic encodeHexEncodedString:hexEncodedSeed]; UIAlertController *alert = [UIAlertController alertControllerWithTitle:title message:mnemonic preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { /* Do nothing */ }]]; [alert addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Copy", @"") style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { UIPasteboard.generalPasteboard.string = mnemonic; }]]; diff --git a/Signal/src/ViewControllers/Registration/OnboardingController.swift b/Signal/src/ViewControllers/Registration/OnboardingController.swift index 5754a54ae..81a4e853f 100644 --- a/Signal/src/ViewControllers/Registration/OnboardingController.swift +++ b/Signal/src/ViewControllers/Registration/OnboardingController.swift @@ -119,14 +119,14 @@ public class OnboardingController: NSObject { private func pushAccountDetailsViewController(from viewController: UIViewController) { AssertIsOnMainThread() - let accountDetailsVC = OnboardingAccountDetailsViewController(onboardingController: self) + let accountDetailsVC = AccountDetailsViewController(onboardingController: self) viewController.navigationController?.pushViewController(accountDetailsVC, animated: true) } func pushKeyPairViewController(from viewController: UIViewController, userName: String?) { AssertIsOnMainThread() - let keyPairVC = OnboardingKeyPairViewController(onboardingController: self, userName: userName) - viewController.navigationController?.pushViewController(keyPairVC, animated: true) + let seedVC = SeedViewController(onboardingController: self, userName: userName) + viewController.navigationController?.pushViewController(seedVC, animated: true) } public func onboardingRegistrationSucceeded(viewController: UIViewController) { diff --git a/SignalServiceKit/src/Account/CreatePreKeysOperation.swift b/SignalServiceKit/src/Account/CreatePreKeysOperation.swift index ea1b091e6..b04e86f07 100644 --- a/SignalServiceKit/src/Account/CreatePreKeysOperation.swift +++ b/SignalServiceKit/src/Account/CreatePreKeysOperation.swift @@ -24,7 +24,7 @@ public class CreatePreKeysOperation: OWSOperation { Logger.debug("") if identityKeyManager.identityKeyPair() == nil { - identityKeyManager.generateNewIdentityKey() + identityKeyManager.generateNewIdentityKeyPair() } // Loki: We don't generate PreKeyRecords here. diff --git a/SignalServiceKit/src/Messages/OWSIdentityManager.h b/SignalServiceKit/src/Messages/OWSIdentityManager.h index 2e193192f..f8f14d41b 100644 --- a/SignalServiceKit/src/Messages/OWSIdentityManager.h +++ b/SignalServiceKit/src/Messages/OWSIdentityManager.h @@ -35,7 +35,8 @@ extern const NSUInteger kStoredIdentityKeyLength; + (instancetype)sharedManager; -- (void)generateNewIdentityKey; +- (void)generateNewIdentityKeyPair; +- (void)generateNewIdentityKeyPairFromSeed:(NSData *)seed; - (void)clearIdentityKey; - (void)setVerificationState:(OWSVerificationState)verificationState diff --git a/SignalServiceKit/src/Messages/OWSIdentityManager.m b/SignalServiceKit/src/Messages/OWSIdentityManager.m index b05cda119..d69b77e4f 100644 --- a/SignalServiceKit/src/Messages/OWSIdentityManager.m +++ b/SignalServiceKit/src/Messages/OWSIdentityManager.m @@ -117,11 +117,16 @@ NSString *const kNSNotificationName_IdentityStateDidChange = @"kNSNotificationNa object:nil]; } -- (void)generateNewIdentityKey +- (void)generateNewIdentityKeyPair { - [self.dbConnection setObject:[Curve25519 generateKeyPair] - forKey:OWSPrimaryStorageIdentityKeyStoreIdentityKey - inCollection:OWSPrimaryStorageIdentityKeyStoreCollection]; + ECKeyPair *keyPair = [Curve25519 generateKeyPair]; + [self.dbConnection setObject:keyPair forKey:OWSPrimaryStorageIdentityKeyStoreIdentityKey inCollection:OWSPrimaryStorageIdentityKeyStoreCollection]; +} + +- (void)generateNewIdentityKeyPairFromSeed:(NSData *)seed +{ + ECKeyPair *keyPair = [Curve25519 generateKeyPairFromSeed:seed]; + [self.dbConnection setObject:keyPair forKey:OWSPrimaryStorageIdentityKeyStoreIdentityKey inCollection:OWSPrimaryStorageIdentityKeyStoreCollection]; } - (void)clearIdentityKey diff --git a/SignalServiceKit/tests/Storage/TSStorageIdentityKeyStoreTests.m b/SignalServiceKit/tests/Storage/TSStorageIdentityKeyStoreTests.m index 2c19170c9..e92f62eaf 100644 --- a/SignalServiceKit/tests/Storage/TSStorageIdentityKeyStoreTests.m +++ b/SignalServiceKit/tests/Storage/TSStorageIdentityKeyStoreTests.m @@ -107,7 +107,7 @@ extern NSString *const OWSPrimaryStorageTrustedKeysCollection; - (void)testIdentityKey { - [[OWSIdentityManager sharedManager] generateNewIdentityKey]; + [[OWSIdentityManager sharedManager] generateNewIdentityKeyPair]; XCTAssert([[[OWSIdentityManager sharedManager] identityKeyPair].publicKey length] == 32); }