From 07418d3f8aa8851e5522c04e01d34126fce0e579 Mon Sep 17 00:00:00 2001 From: Niels Andriesse Date: Wed, 25 Sep 2019 12:22:34 +1000 Subject: [PATCH] Debug --- Signal/src/AppDelegate.h | 1 + Signal/src/Loki/Onboarding/SeedVC.swift | 16 +++++++++--- .../Loki/Settings/DeviceLinkingModal.swift | 25 +++++++++++++----- .../Settings/DeviceLinkingModalDelegate.swift | 4 ++- Signal/src/Loki/Settings/SeedModal.swift | 14 ++++++++-- Signal/src/Loki/Utilities/Modal.swift | 2 +- .../translations/en.lproj/Localizable.strings | 9 ++++--- .../src/Loki/API/LokiStorageAPI.swift | 2 +- .../Multi Device/DeviceLinkingSession.swift | 26 +++++++++++++------ .../Multi Device/DeviceLinkingUtilities.swift | 16 +++++++----- .../src/Loki/Messaging/LKDeviceLinkMessage.h | 9 ++++++- .../src/Loki/Messaging/LKDeviceLinkMessage.m | 14 +++++++++- .../src/Loki/Utilities/String+Trimming.swift | 17 ++++++++++++ .../src/Messages/OWSMessageManager.m | 4 --- .../src/Messages/OWSMessageSender.m | 16 +++++++----- 15 files changed, 129 insertions(+), 46 deletions(-) create mode 100644 SignalServiceKit/src/Loki/Utilities/String+Trimming.swift diff --git a/Signal/src/AppDelegate.h b/Signal/src/AppDelegate.h index 762c9df57..273023d2a 100644 --- a/Signal/src/AppDelegate.h +++ b/Signal/src/AppDelegate.h @@ -8,6 +8,7 @@ extern NSString *const AppDelegateStoryboardMain; @interface AppDelegate : UIResponder +- (void)startLongPollerIfNeeded; - (void)stopLongPollerIfNeeded; - (void)createGroupChatsIfNeeded; - (void)createRSSFeedsIfNeeded; diff --git a/Signal/src/Loki/Onboarding/SeedVC.swift b/Signal/src/Loki/Onboarding/SeedVC.swift index 443eea814..07088a4b8 100644 --- a/Signal/src/Loki/Onboarding/SeedVC.swift +++ b/Signal/src/Loki/Onboarding/SeedVC.swift @@ -124,7 +124,7 @@ final class SeedVC : OnboardingBaseViewController, DeviceLinkingModalDelegate { }() private lazy var explanationLabel3: UILabel = { - let result = createExplanationLabel(text: NSLocalizedString("Link to an existing device by going into Loki Messenger's in-app settings and clicking \"Link Device\".", comment: "")) + let result = createExplanationLabel(text: NSLocalizedString("Link to an existing device by going into its in-app settings and clicking \"Link Device\".", comment: "")) result.accessibilityIdentifier = "onboarding.keyPairStep.explanationLabel3" result.textColor = Theme.primaryColor var fontTraits = result.font.fontDescriptor.symbolicTraits @@ -154,7 +154,7 @@ final class SeedVC : OnboardingBaseViewController, DeviceLinkingModalDelegate { result.textColor = Theme.primaryColor result.font = UIFont.ows_dynamicTypeBodyClamped result.textAlignment = .center - let placeholder = NSMutableAttributedString(string: NSLocalizedString("Enter Your Primary Account's Public Key", comment: "")) + let placeholder = NSMutableAttributedString(string: NSLocalizedString("Enter the Other Device's Public Key", comment: "")) placeholder.addAttribute(.foregroundColor, value: Theme.placeholderColor, range: NSRange(location: 0, length: placeholder.length)) result.attributedPlaceholder = placeholder result.tintColor = UIColor.lokiGreen() @@ -337,20 +337,28 @@ final class SeedVC : OnboardingBaseViewController, DeviceLinkingModalDelegate { case .link: Analytics.shared.track("Device Linked") } if mode == .link { + TSAccountManager.sharedInstance().didRegister() + let appDelegate = UIApplication.shared.delegate as! AppDelegate + appDelegate.startLongPollerIfNeeded() let deviceLinkingModal = DeviceLinkingModal(mode: .slave, delegate: self) deviceLinkingModal.modalPresentationStyle = .overFullScreen present(deviceLinkingModal, animated: true, completion: nil) let masterHexEncodedPublicKey = masterHexEncodedPublicKeyTextField.text!.trimmingCharacters(in: CharacterSet.whitespaces) let linkingRequestMessage = DeviceLinkingUtilities.getLinkingRequestMessage(for: masterHexEncodedPublicKey) - ThreadUtil.enqueue(linkingRequestMessage) + (0..<8).forEach { _ in ThreadUtil.enqueue(linkingRequestMessage) } } else { onboardingController.pushDisplayNameVC(from: self) } } func handleDeviceLinkAuthorized(_ deviceLink: DeviceLink) { - TSAccountManager.sharedInstance().didRegister() UserDefaults.standard.set(true, forKey: "didUpdateForMainnet") onboardingController.verificationDidComplete(fromView: self) } + + func handleDeviceLinkingModalDismissed() { + let appDelegate = UIApplication.shared.delegate as! AppDelegate + appDelegate.stopLongPollerIfNeeded() + TSAccountManager.sharedInstance().resetForReregistration() + } } diff --git a/Signal/src/Loki/Settings/DeviceLinkingModal.swift b/Signal/src/Loki/Settings/DeviceLinkingModal.swift index 244bd9ef9..9956d923e 100644 --- a/Signal/src/Loki/Settings/DeviceLinkingModal.swift +++ b/Signal/src/Loki/Settings/DeviceLinkingModal.swift @@ -95,13 +95,13 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate { }() subtitleLabel.text = { switch mode { - case .master: return NSLocalizedString("Click the \"Link Device\" button on your other device to start the linking process", comment: "") - case .slave: return NSLocalizedString("Please verify that the words below match the ones shown on your other device.", comment: "") + case .master: return NSLocalizedString("Create a new account on your other device and click \"Link Device\" when you're at the \"Create Your Loki Messenger Account\" step to start the linking process", comment: "") + case .slave: return NSLocalizedString("Please check that the words below match the ones shown on your other device", comment: "") } }() mnemonicLabel.isHidden = (mode == .master) if mode == .slave { - let hexEncodedPublicKey = OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey + let hexEncodedPublicKey = OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey.removing05PrefixIfNeeded() mnemonicLabel.text = Mnemonic.encode(hexEncodedString: hexEncodedPublicKey).split(separator: " ")[0..<3].joined(separator: " ") } let buttonHeight = cancelButton.button.titleLabel!.font.pointSize * 48 / 17 @@ -121,8 +121,9 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate { spinner.stopAnimating() spinner.isHidden = true titleLabel.text = NSLocalizedString("Linking Request Received", comment: "") - subtitleLabel.text = NSLocalizedString("Please check that the words below match the words shown on the device being linked.", comment: "") - mnemonicLabel.text = Mnemonic.encode(hexEncodedString: deviceLink.slave.hexEncodedPublicKey).split(separator: " ")[0..<3].joined(separator: " ") + subtitleLabel.text = NSLocalizedString("Please check that the words below match the ones shown on your other device", comment: "") + let hexEncodedPublicKey = deviceLink.slave.hexEncodedPublicKey.removing05PrefixIfNeeded() + mnemonicLabel.text = Mnemonic.encode(hexEncodedString: hexEncodedPublicKey).split(separator: " ")[0..<3].joined(separator: " ") mnemonicLabel.isHidden = false authorizeButton.isHidden = false } @@ -130,13 +131,25 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate { @objc private func authorizeDeviceLink() { let deviceLink = self.deviceLink! let linkingAuthorizationMessage = DeviceLinkingUtilities.getLinkingAuthorizationMessage(for: deviceLink) - ThreadUtil.enqueue(linkingAuthorizationMessage) + (0..<8).forEach { _ in ThreadUtil.enqueue(linkingAuthorizationMessage) } let session = DeviceLinkingSession.current! session.stopListeningForLinkingRequests() + session.markLinkingRequestAsProcessed() dismiss(animated: true, completion: nil) } func handleDeviceLinkAuthorized(_ deviceLink: DeviceLink) { + let session = DeviceLinkingSession.current! + session.stopListeningForLinkingAuthorization() delegate?.handleDeviceLinkAuthorized(deviceLink) + dismiss(animated: true, completion: nil) + } + + @objc override func cancel() { + let session = DeviceLinkingSession.current! + session.stopListeningForLinkingRequests() + session.markLinkingRequestAsProcessed() // Only relevant in master mode + delegate?.handleDeviceLinkingModalDismissed() // Only relevant in slave mode + dismiss(animated: true, completion: nil) } } diff --git a/Signal/src/Loki/Settings/DeviceLinkingModalDelegate.swift b/Signal/src/Loki/Settings/DeviceLinkingModalDelegate.swift index 54737b518..f8586401f 100644 --- a/Signal/src/Loki/Settings/DeviceLinkingModalDelegate.swift +++ b/Signal/src/Loki/Settings/DeviceLinkingModalDelegate.swift @@ -2,9 +2,11 @@ @objc protocol DeviceLinkingModalDelegate { func handleDeviceLinkAuthorized(_ deviceLink: DeviceLink) + func handleDeviceLinkingModalDismissed() } extension DeviceLinkingModalDelegate { - func handleDeviceLinkAuthorized(_ deviceLink: DeviceLink) { /* Do nothing */ } + func handleDeviceLinkAuthorized(_ deviceLink: DeviceLink) { /* Do nothing */ } + func handleDeviceLinkingModalDismissed() { /* Do nothing */ } } diff --git a/Signal/src/Loki/Settings/SeedModal.swift b/Signal/src/Loki/Settings/SeedModal.swift index 9318b08f5..84cf3802c 100644 --- a/Signal/src/Loki/Settings/SeedModal.swift +++ b/Signal/src/Loki/Settings/SeedModal.swift @@ -23,14 +23,24 @@ final class SeedModal : Modal { titleLabel.numberOfLines = 0 titleLabel.lineBreakMode = .byWordWrapping titleLabel.textAlignment = .center + // Subtitle label + let subtitleLabel = UILabel() + subtitleLabel.textColor = Theme.primaryColor + subtitleLabel.font = UIFont.ows_dynamicTypeCaption1Clamped + subtitleLabel.text = NSLocalizedString("This is your personal secret. It can be used to restore your account if you lose access, or to migrate to a new device.", comment: "") + subtitleLabel.numberOfLines = 0 + subtitleLabel.lineBreakMode = .byWordWrapping + subtitleLabel.textAlignment = .center // Mnemonic label let mnemonicLabel = UILabel() - mnemonicLabel.font = UIFont.ows_dynamicTypeCaption1Clamped + let font = UIFont.ows_dynamicTypeCaption1Clamped + mnemonicLabel.font = UIFont(descriptor: font.fontDescriptor.withSymbolicTraits(.traitItalic)!, size: font.pointSize) mnemonicLabel.text = mnemonic mnemonicLabel.numberOfLines = 0 mnemonicLabel.textAlignment = .center mnemonicLabel.lineBreakMode = .byWordWrapping mnemonicLabel.textColor = UIColor.ows_white + mnemonicLabel.alpha = 0.8 // Button stack view let copyButton = OWSFlatButton.button(title: NSLocalizedString("Copy", comment: ""), font: .ows_dynamicTypeBodyClamped, titleColor: .white, backgroundColor: .clear, target: self, selector: #selector(copySeed)) copyButton.setBackgroundColors(upColor: .clear, downColor: .clear) @@ -41,7 +51,7 @@ final class SeedModal : Modal { copyButton.set(.height, to: buttonHeight) cancelButton.set(.height, to: buttonHeight) // Stack view - let stackView = UIStackView(arrangedSubviews: [ UIView.spacer(withHeight: 2), titleLabel, mnemonicLabel, buttonStackView ]) + let stackView = UIStackView(arrangedSubviews: [ UIView.spacer(withHeight: 2), titleLabel, subtitleLabel, mnemonicLabel, buttonStackView ]) stackView.axis = .vertical stackView.spacing = 16 contentView.addSubview(stackView) diff --git a/Signal/src/Loki/Utilities/Modal.swift b/Signal/src/Loki/Utilities/Modal.swift index 97f1241d6..e2a2ff8c0 100644 --- a/Signal/src/Loki/Utilities/Modal.swift +++ b/Signal/src/Loki/Utilities/Modal.swift @@ -51,7 +51,7 @@ internal class Modal : UIViewController { } } - @objc private func cancel() { + @objc func cancel() { dismiss(animated: true, completion: nil) } } diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index b6480af45..f4d6d41f2 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -2624,8 +2624,11 @@ "Link Device" = "Link Device"; "Waiting for Device" = "Waiting for Device"; "Waiting for Authorization" = "Waiting for Authorization"; -"Click the \"Link Device\" button on your other device to start the linking process" = "Click the \"Link Device\" button on your other device to start the linking process"; +"Create a new account on your other device and click \"Link Device\" when you're at the \"Create Your Loki Messenger Account\" step to start the linking process" = "Create a new account on your other device and click \"Link Device\" when you're at the \"Create Your Loki Messenger Account\" step to start the linking process"; "Linking Request Received" = "Linking Request Received"; "Invalid public key" = "Invalid public key"; -"Please verify that the words below match the ones shown on your other device." = "Please verify that the words below match the ones shown on your other device."; -"Link to an existing device by going into Loki Messenger's in-app settings and clicking \"Link Device\"." = "Link to an existing device by going into Loki Messenger's in-app settings and clicking \"Link Device\"."; +"Please check that the words below match the ones shown on your other device" = "Please check that the words below match the ones shown on your other device"; +"Link to an existing device by going into its in-app settings and clicking \"Link Device\"." = "Link to an existing device by going into its in-app settings and clicking \"Link Device\"."; +"Authorize" = "Authorize"; +"Enter the Other Device's Public Key" = "Enter the Other Device's Public Key"; +"This is your personal secret. It can be used to restore your account if you lose access, or to migrate to a new device." = "This is your personal secret. It can be used to restore your account if you lose access, or to migrate to a new device."; diff --git a/SignalServiceKit/src/Loki/API/LokiStorageAPI.swift b/SignalServiceKit/src/Loki/API/LokiStorageAPI.swift index ad3fb77fc..c21bd16ca 100644 --- a/SignalServiceKit/src/Loki/API/LokiStorageAPI.swift +++ b/SignalServiceKit/src/Loki/API/LokiStorageAPI.swift @@ -20,6 +20,6 @@ public final class LokiStorageAPI : NSObject { public static func getDeviceLinks(associatedWith hexEncodedPublicKey: String) -> Promise> { // Gets the device links associated with the given hex encoded public key from the // server and stores and returns the valid ones - notImplemented() + return Promise.value(Set()) } } diff --git a/SignalServiceKit/src/Loki/API/Multi Device/DeviceLinkingSession.swift b/SignalServiceKit/src/Loki/API/Multi Device/DeviceLinkingSession.swift index 564e857db..54e32534b 100644 --- a/SignalServiceKit/src/Loki/API/Multi Device/DeviceLinkingSession.swift +++ b/SignalServiceKit/src/Loki/API/Multi Device/DeviceLinkingSession.swift @@ -5,6 +5,7 @@ import PromiseKit public final class DeviceLinkingSession : NSObject { private let delegate: DeviceLinkingSessionDelegate @objc public var isListeningForLinkingRequests = false + @objc public var isProcessingLinkingRequest = false @objc public var isListeningForLinkingAuthorization = false // MARK: Lifecycle @@ -30,21 +31,26 @@ public final class DeviceLinkingSession : NSObject { } @objc public func processLinkingRequest(from slaveHexEncodedPublicKey: String, to masterHexEncodedPublicKey: String, with slaveSignature: Data) { - guard isListeningForLinkingRequests, masterHexEncodedPublicKey == OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey else { return } + guard isListeningForLinkingRequests, !isProcessingLinkingRequest, masterHexEncodedPublicKey.removing05PrefixIfNeeded() == OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey.removing05PrefixIfNeeded() else { return } let master = DeviceLink.Device(hexEncodedPublicKey: masterHexEncodedPublicKey) let slave = DeviceLink.Device(hexEncodedPublicKey: slaveHexEncodedPublicKey, signature: slaveSignature) let deviceLink = DeviceLink(between: master, and: slave) guard hasValidSlaveSignature(deviceLink) else { return } - delegate.requestUserAuthorization(for: deviceLink) + isProcessingLinkingRequest = true + DispatchQueue.main.async { + self.delegate.requestUserAuthorization(for: deviceLink) + } } @objc public func processLinkingAuthorization(from masterHexEncodedPublicKey: String, for slaveHexEncodedPublicKey: String, masterSignature: Data, slaveSignature: Data) { - guard isListeningForLinkingAuthorization, slaveHexEncodedPublicKey == OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey else { return } + guard isListeningForLinkingAuthorization, slaveHexEncodedPublicKey.removing05PrefixIfNeeded() == OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey.removing05PrefixIfNeeded() else { return } let master = DeviceLink.Device(hexEncodedPublicKey: masterHexEncodedPublicKey, signature: masterSignature) let slave = DeviceLink.Device(hexEncodedPublicKey: slaveHexEncodedPublicKey, signature: slaveSignature) let deviceLink = DeviceLink(between: master, and: slave) guard hasValidSlaveSignature(deviceLink) && hasValidMasterSignature(deviceLink) else { return } - delegate.handleDeviceLinkAuthorized(deviceLink) + DispatchQueue.main.async { + self.delegate.handleDeviceLinkAuthorized(deviceLink) + } } public func stopListeningForLinkingRequests() { @@ -57,6 +63,10 @@ public final class DeviceLinkingSession : NSObject { isListeningForLinkingAuthorization = false } + public func markLinkingRequestAsProcessed() { + isProcessingLinkingRequest = false + } + // MARK: Private API // When requesting a device link, the slave device signs the master device's public key. When authorizing @@ -64,15 +74,15 @@ public final class DeviceLinkingSession : NSObject { private func hasValidSlaveSignature(_ deviceLink: DeviceLink) -> Bool { guard let slaveSignature = deviceLink.slave.signature else { return false } - let slavePublicKey = Data(hex: deviceLink.slave.hexEncodedPublicKey) - let masterPublicKey = Data(hex: deviceLink.master.hexEncodedPublicKey) + let slavePublicKey = Data(hex: deviceLink.slave.hexEncodedPublicKey.removing05PrefixIfNeeded()) + let masterPublicKey = Data(hex: deviceLink.master.hexEncodedPublicKey.removing05PrefixIfNeeded()) return (try? Ed25519.verifySignature(slaveSignature, publicKey: slavePublicKey, data: masterPublicKey)) ?? false } private func hasValidMasterSignature(_ deviceLink: DeviceLink) -> Bool { guard let masterSignature = deviceLink.master.signature else { return false } - let slavePublicKey = Data(hex: deviceLink.slave.hexEncodedPublicKey) - let masterPublicKey = Data(hex: deviceLink.master.hexEncodedPublicKey) + let slavePublicKey = Data(hex: deviceLink.slave.hexEncodedPublicKey.removing05PrefixIfNeeded()) + let masterPublicKey = Data(hex: deviceLink.master.hexEncodedPublicKey.removing05PrefixIfNeeded()) return (try? Ed25519.verifySignature(masterSignature, publicKey: masterPublicKey, data: slavePublicKey)) ?? false } } diff --git a/SignalServiceKit/src/Loki/API/Multi Device/DeviceLinkingUtilities.swift b/SignalServiceKit/src/Loki/API/Multi Device/DeviceLinkingUtilities.swift index 91073079f..fa2c7fc29 100644 --- a/SignalServiceKit/src/Loki/API/Multi Device/DeviceLinkingUtilities.swift +++ b/SignalServiceKit/src/Loki/API/Multi Device/DeviceLinkingUtilities.swift @@ -6,19 +6,21 @@ public enum DeviceLinkingUtilities { public static func getLinkingRequestMessage(for masterHexEncodedPublicKey: String) -> DeviceLinkMessage { let slaveKeyPair = OWSIdentityManager.shared().identityKeyPair()! - let slaveHexEncodedPublicKey = slaveKeyPair.hexEncodedPublicKey - let slaveSignature = try! Ed25519.sign(Data(hex: masterHexEncodedPublicKey), with: slaveKeyPair) + let slaveHexEncodedPublicKey = slaveKeyPair.hexEncodedPublicKey.removing05PrefixIfNeeded() + let slaveSignature = try! Ed25519.sign(Data(hex: masterHexEncodedPublicKey.removing05PrefixIfNeeded()), with: slaveKeyPair) let thread = TSContactThread.getOrCreateThread(contactId: masterHexEncodedPublicKey) - return DeviceLinkMessage(in: thread, masterHexEncodedPublicKey: masterHexEncodedPublicKey, slaveHexEncodedPublicKey: slaveHexEncodedPublicKey, masterSignature: nil, slaveSignature: slaveSignature) + return DeviceLinkMessage(in: thread, masterHexEncodedPublicKey: masterHexEncodedPublicKey.removing05PrefixIfNeeded(), slaveHexEncodedPublicKey: slaveHexEncodedPublicKey, + masterSignature: nil, slaveSignature: slaveSignature, kind: .request) } public static func getLinkingAuthorizationMessage(for deviceLink: DeviceLink) -> DeviceLinkMessage { let masterKeyPair = OWSIdentityManager.shared().identityKeyPair()! - let masterHexEncodedPublicKey = masterKeyPair.hexEncodedPublicKey + let masterHexEncodedPublicKey = masterKeyPair.hexEncodedPublicKey.removing05PrefixIfNeeded() let slaveHexEncodedPublicKey = deviceLink.slave.hexEncodedPublicKey - let masterSignature = try! Ed25519.sign(Data(hex: slaveHexEncodedPublicKey), with: masterKeyPair) + let masterSignature = try! Ed25519.sign(Data(hex: slaveHexEncodedPublicKey.removing05PrefixIfNeeded()), with: masterKeyPair) let slaveSignature = deviceLink.slave.signature! - let thread = TSContactThread.getOrCreateThread(contactId: slaveHexEncodedPublicKey) - return DeviceLinkMessage(in: thread, masterHexEncodedPublicKey: masterHexEncodedPublicKey, slaveHexEncodedPublicKey: slaveHexEncodedPublicKey, masterSignature: masterSignature, slaveSignature: slaveSignature) + let thread = TSContactThread.getOrCreateThread(contactId: slaveHexEncodedPublicKey.adding05PrefixIfNeeded()) + return DeviceLinkMessage(in: thread, masterHexEncodedPublicKey: masterHexEncodedPublicKey, slaveHexEncodedPublicKey: slaveHexEncodedPublicKey.removing05PrefixIfNeeded(), + masterSignature: masterSignature, slaveSignature: slaveSignature, kind: .authorization) } } diff --git a/SignalServiceKit/src/Loki/Messaging/LKDeviceLinkMessage.h b/SignalServiceKit/src/Loki/Messaging/LKDeviceLinkMessage.h index ff3218935..0e3d1cd6c 100644 --- a/SignalServiceKit/src/Loki/Messaging/LKDeviceLinkMessage.h +++ b/SignalServiceKit/src/Loki/Messaging/LKDeviceLinkMessage.h @@ -1,5 +1,11 @@ #import "TSOutgoingMessage.h" +typedef NS_ENUM(NSUInteger, LKDeviceLinkMessageKind) { + LKDeviceLinkMessageKindRequest = 1, + LKDeviceLinkMessageKindAuthorization = 2, + LKDeviceLinkMessageKindRevocation = 3 +}; + NS_SWIFT_NAME(DeviceLinkMessage) @interface LKDeviceLinkMessage : TSOutgoingMessage @@ -7,8 +13,9 @@ NS_SWIFT_NAME(DeviceLinkMessage) @property (nonatomic, readonly) NSString *slaveHexEncodedPublicKey; @property (nonatomic, readonly) NSData *masterSignature; // nil for device linking requests @property (nonatomic, readonly) NSData *slaveSignature; +@property (nonatomic, readonly) LKDeviceLinkMessageKind kind; - (instancetype)initInThread:(TSThread *)thread masterHexEncodedPublicKey:(NSString *)masterHexEncodedPublicKey slaveHexEncodedPublicKey:(NSString *)slaveHexEncodedPublicKey - masterSignature:(NSData *)masterSignature slaveSignature:(NSData *)slaveSignature; + masterSignature:(NSData *)masterSignature slaveSignature:(NSData *)slaveSignature kind:(LKDeviceLinkMessageKind)kind; @end diff --git a/SignalServiceKit/src/Loki/Messaging/LKDeviceLinkMessage.m b/SignalServiceKit/src/Loki/Messaging/LKDeviceLinkMessage.m index b217e33b0..0f6209e13 100644 --- a/SignalServiceKit/src/Loki/Messaging/LKDeviceLinkMessage.m +++ b/SignalServiceKit/src/Loki/Messaging/LKDeviceLinkMessage.m @@ -8,7 +8,7 @@ @implementation LKDeviceLinkMessage - (instancetype)initInThread:(TSThread *)thread masterHexEncodedPublicKey:(NSString *)masterHexEncodedPublicKey slaveHexEncodedPublicKey:(NSString *)slaveHexEncodedPublicKey - masterSignature:(NSData *)masterSignature slaveSignature:(NSData *)slaveSignature { + masterSignature:(NSData *)masterSignature slaveSignature:(NSData *)slaveSignature kind:(LKDeviceLinkMessageKind)kind { self = [self initOutgoingMessageWithTimestamp:NSDate.ows_millisecondTimeStamp inThread:thread messageBody:@"" attachmentIds:[NSMutableArray new] expiresInSeconds:0 expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMetaMessageUnspecified quotedMessage:nil contactShare:nil linkPreview:nil]; if (self) { @@ -16,6 +16,7 @@ _slaveHexEncodedPublicKey = slaveHexEncodedPublicKey; _masterSignature = masterSignature; _slaveSignature = slaveSignature; + _kind = kind; } return self; } @@ -26,6 +27,17 @@ [deviceLinkMessageBuilder setSlaveHexEncodedPublicKey:self.slaveHexEncodedPublicKey]; if (self.masterSignature != nil) { [deviceLinkMessageBuilder setMasterSignature:self.masterSignature]; } [deviceLinkMessageBuilder setSlaveSignature:self.slaveSignature]; + switch (self.kind) { + case LKDeviceLinkMessageKindRequest: + [deviceLinkMessageBuilder setType:SSKProtoLokiDeviceLinkMessageTypeRequest]; + break; + case LKDeviceLinkMessageKindAuthorization: + [deviceLinkMessageBuilder setType:SSKProtoLokiDeviceLinkMessageTypeAuthorization]; + break; + case LKDeviceLinkMessageKindRevocation: + [deviceLinkMessageBuilder setType:SSKProtoLokiDeviceLinkMessageTypeRevocation]; + break; + } NSError *error; SSKProtoLokiDeviceLinkMessage *deviceLinkMessage = [deviceLinkMessageBuilder buildAndReturnError:&error]; if (error || deviceLinkMessage == nil) { diff --git a/SignalServiceKit/src/Loki/Utilities/String+Trimming.swift b/SignalServiceKit/src/Loki/Utilities/String+Trimming.swift new file mode 100644 index 000000000..90703ef4f --- /dev/null +++ b/SignalServiceKit/src/Loki/Utilities/String+Trimming.swift @@ -0,0 +1,17 @@ + +public extension String { + + public func removing05PrefixIfNeeded() -> String { + var result = self + if result.count == 66 && result.hasPrefix("05") { result.removeFirst(2) } + return result + } + + public func adding05PrefixIfNeeded() -> String { + if count == 64 { + return "05" + self + } else { + return self + } + } +} diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index 6672d9158..bf29ce3e7 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -1597,10 +1597,6 @@ NS_ASSUME_NONNULL_BEGIN } } -- (void)handleDeviceLinkMessageIfNeeded:(TSIncomingMessage *)message transaction:(YapDatabaseReadWriteTransaction *)transaction { - -} - - (void)finalizeIncomingMessage:(TSIncomingMessage *)incomingMessage thread:(TSThread *)thread envelope:(SSKProtoEnvelope *)envelope diff --git a/SignalServiceKit/src/Messages/OWSMessageSender.m b/SignalServiceKit/src/Messages/OWSMessageSender.m index c6ab8afdd..19734a3ad 100644 --- a/SignalServiceKit/src/Messages/OWSMessageSender.m +++ b/SignalServiceKit/src/Messages/OWSMessageSender.m @@ -44,6 +44,7 @@ #import "TSSocketManager.h" #import "TSThread.h" #import "LKFriendRequestMessage.h" +#import "LKDeviceLinkMessage.h" #import "LKAddressMessage.h" #import #import @@ -1553,10 +1554,10 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; // This may involve blocking network requests, so we do it _before_ // we open a transaction. - // A friend request means we don't have a session with the person - // There's no point to check for it + // Loki: Both for friend request messages and device link messages we don't require a session BOOL isFriendRequest = [messageSend.message isKindOfClass:LKFriendRequestMessage.class]; - if (!isFriendRequest) { + BOOL isDeviceLinkMessage = [messageSend.message isKindOfClass:LKDeviceLinkMessage.class]; + if (!isFriendRequest && !isDeviceLinkMessage) { [self throws_ensureRecipientHasSessionForMessageSend:messageSend deviceId:deviceId]; } @@ -1743,7 +1744,7 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; }) retainUntilComplete]; } -- (nullable NSDictionary *)throws_encryptedFriendMessageForMessageSend:(OWSMessageSend *)messageSend +- (nullable NSDictionary *)throws_encryptedFriendRequestOrDeviceLinkMessageForMessageSend:(OWSMessageSend *)messageSend deviceId:(NSNumber *)deviceId plainText:(NSData *)plainText { @@ -1802,10 +1803,11 @@ NSString *const OWSMessageSenderRateLimitedException = @"RateLimitedException"; NSString *recipientId = recipient.recipientId; OWSAssertDebug(recipientId.length > 0); - // Loki: Handle friend requests differently + // Loki: Both for friend request messages and device link messages we use fallback encryption as we don't necessarily have a session yet BOOL isFriendRequest = [messageSend.message isKindOfClass:LKFriendRequestMessage.class]; - if (isFriendRequest) { - return [self throws_encryptedFriendMessageForMessageSend:messageSend deviceId:deviceId plainText:plainText]; + BOOL isDeviceLinkMessage = [messageSend.message isKindOfClass:LKDeviceLinkMessage.class]; + if (isFriendRequest || isDeviceLinkMessage) { + return [self throws_encryptedFriendRequestOrDeviceLinkMessageForMessageSend:messageSend deviceId:deviceId plainText:plainText]; } // This may throw an exception.