This commit is contained in:
Niels Andriesse 2019-09-25 16:30:45 +10:00
parent 07418d3f8a
commit 21dd3318d6
11 changed files with 38 additions and 162 deletions

View file

@ -345,7 +345,7 @@ final class SeedVC : OnboardingBaseViewController, DeviceLinkingModalDelegate {
present(deviceLinkingModal, animated: true, completion: nil)
let masterHexEncodedPublicKey = masterHexEncodedPublicKeyTextField.text!.trimmingCharacters(in: CharacterSet.whitespaces)
let linkingRequestMessage = DeviceLinkingUtilities.getLinkingRequestMessage(for: masterHexEncodedPublicKey)
(0..<8).forEach { _ in ThreadUtil.enqueue(linkingRequestMessage) }
(0..<4).forEach { _ in ThreadUtil.enqueue(linkingRequestMessage) }
} else {
onboardingController.pushDisplayNameVC(from: self)
}

View file

@ -131,7 +131,7 @@ final class DeviceLinkingModal : Modal, DeviceLinkingSessionDelegate {
@objc private func authorizeDeviceLink() {
let deviceLink = self.deviceLink!
let linkingAuthorizationMessage = DeviceLinkingUtilities.getLinkingAuthorizationMessage(for: deviceLink)
(0..<8).forEach { _ in ThreadUtil.enqueue(linkingAuthorizationMessage) }
(0..<4).forEach { _ in ThreadUtil.enqueue(linkingAuthorizationMessage) }
let session = DeviceLinkingSession.current!
session.stopListeningForLinkingRequests()
session.markLinkingRequestAsProcessed()

View file

@ -87,16 +87,10 @@ message LokiAddressMessage { // Loki
}
message LokiDeviceLinkMessage { // Loki
enum Type {
REQUEST = 1;
AUTHORIZATION = 2;
REVOCATION = 3;
}
optional string masterHexEncodedPublicKey = 1;
optional string slaveHexEncodedPublicKey = 2;
optional bytes masterSignature = 3;
optional bytes slaveSignature = 4;
optional Type type = 5;
}
message CallMessage {

View file

@ -31,7 +31,7 @@ public final class DeviceLinkingSession : NSObject {
}
@objc public func processLinkingRequest(from slaveHexEncodedPublicKey: String, to masterHexEncodedPublicKey: String, with slaveSignature: Data) {
guard isListeningForLinkingRequests, !isProcessingLinkingRequest, masterHexEncodedPublicKey.removing05PrefixIfNeeded() == OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey.removing05PrefixIfNeeded() else { return }
guard isListeningForLinkingRequests, !isProcessingLinkingRequest, masterHexEncodedPublicKey == OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey else { return }
let master = DeviceLink.Device(hexEncodedPublicKey: masterHexEncodedPublicKey)
let slave = DeviceLink.Device(hexEncodedPublicKey: slaveHexEncodedPublicKey, signature: slaveSignature)
let deviceLink = DeviceLink(between: master, and: slave)
@ -43,7 +43,7 @@ public final class DeviceLinkingSession : NSObject {
}
@objc public func processLinkingAuthorization(from masterHexEncodedPublicKey: String, for slaveHexEncodedPublicKey: String, masterSignature: Data, slaveSignature: Data) {
guard isListeningForLinkingAuthorization, slaveHexEncodedPublicKey.removing05PrefixIfNeeded() == OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey.removing05PrefixIfNeeded() else { return }
guard isListeningForLinkingAuthorization, slaveHexEncodedPublicKey == OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey 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)
@ -75,14 +75,16 @@ 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.removing05PrefixIfNeeded())
let masterPublicKey = Data(hex: deviceLink.master.hexEncodedPublicKey.removing05PrefixIfNeeded())
return (try? Ed25519.verifySignature(slaveSignature, publicKey: slavePublicKey, data: masterPublicKey)) ?? false
var kind = LKDeviceLinkMessageKind.request
let data = Data(hex: deviceLink.master.hexEncodedPublicKey) + Data(bytes: &kind, count: MemoryLayout.size(ofValue: kind))
return (try? Ed25519.verifySignature(slaveSignature, publicKey: slavePublicKey, data: data)) ?? false
}
private func hasValidMasterSignature(_ deviceLink: DeviceLink) -> Bool {
guard let masterSignature = deviceLink.master.signature else { return false }
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
var kind = LKDeviceLinkMessageKind.authorization
let data = Data(hex: deviceLink.slave.hexEncodedPublicKey) + Data(bytes: &kind, count: MemoryLayout.size(ofValue: kind))
return (try? Ed25519.verifySignature(masterSignature, publicKey: masterPublicKey, data: data)) ?? false
}
}

View file

@ -6,21 +6,23 @@ public enum DeviceLinkingUtilities {
public static func getLinkingRequestMessage(for masterHexEncodedPublicKey: String) -> DeviceLinkMessage {
let slaveKeyPair = OWSIdentityManager.shared().identityKeyPair()!
let slaveHexEncodedPublicKey = slaveKeyPair.hexEncodedPublicKey.removing05PrefixIfNeeded()
let slaveSignature = try! Ed25519.sign(Data(hex: masterHexEncodedPublicKey.removing05PrefixIfNeeded()), with: slaveKeyPair)
let slaveHexEncodedPublicKey = slaveKeyPair.hexEncodedPublicKey
var kind = LKDeviceLinkMessageKind.request
let data = Data(hex: masterHexEncodedPublicKey) + Data(bytes: &kind, count: MemoryLayout.size(ofValue: kind))
let slaveSignature = try! Ed25519.sign(data, with: slaveKeyPair)
let thread = TSContactThread.getOrCreateThread(contactId: masterHexEncodedPublicKey)
return DeviceLinkMessage(in: thread, masterHexEncodedPublicKey: masterHexEncodedPublicKey.removing05PrefixIfNeeded(), slaveHexEncodedPublicKey: slaveHexEncodedPublicKey,
masterSignature: nil, slaveSignature: slaveSignature, kind: .request)
return DeviceLinkMessage(in: thread, masterHexEncodedPublicKey: masterHexEncodedPublicKey, slaveHexEncodedPublicKey: slaveHexEncodedPublicKey, masterSignature: nil, slaveSignature: slaveSignature)
}
public static func getLinkingAuthorizationMessage(for deviceLink: DeviceLink) -> DeviceLinkMessage {
let masterKeyPair = OWSIdentityManager.shared().identityKeyPair()!
let masterHexEncodedPublicKey = masterKeyPair.hexEncodedPublicKey.removing05PrefixIfNeeded()
let masterHexEncodedPublicKey = masterKeyPair.hexEncodedPublicKey
let slaveHexEncodedPublicKey = deviceLink.slave.hexEncodedPublicKey
let masterSignature = try! Ed25519.sign(Data(hex: slaveHexEncodedPublicKey.removing05PrefixIfNeeded()), with: masterKeyPair)
var kind = LKDeviceLinkMessageKind.authorization
let data = Data(hex: slaveHexEncodedPublicKey) + Data(bytes: &kind, count: MemoryLayout.size(ofValue: kind))
let masterSignature = try! Ed25519.sign(data, with: masterKeyPair)
let slaveSignature = deviceLink.slave.signature!
let thread = TSContactThread.getOrCreateThread(contactId: slaveHexEncodedPublicKey.adding05PrefixIfNeeded())
return DeviceLinkMessage(in: thread, masterHexEncodedPublicKey: masterHexEncodedPublicKey, slaveHexEncodedPublicKey: slaveHexEncodedPublicKey.removing05PrefixIfNeeded(),
masterSignature: masterSignature, slaveSignature: slaveSignature, kind: .authorization)
let thread = TSContactThread.getOrCreateThread(contactId: slaveHexEncodedPublicKey)
return DeviceLinkMessage(in: thread, masterHexEncodedPublicKey: masterHexEncodedPublicKey, slaveHexEncodedPublicKey: slaveHexEncodedPublicKey, masterSignature: masterSignature, slaveSignature: slaveSignature)
}
}

View file

@ -15,7 +15,6 @@ NS_SWIFT_NAME(DeviceLinkMessage)
@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 kind:(LKDeviceLinkMessageKind)kind;
- (instancetype)initInThread:(TSThread *)thread masterHexEncodedPublicKey:(NSString *)masterHexEncodedPublicKey slaveHexEncodedPublicKey:(NSString *)slaveHexEncodedPublicKey masterSignature:(NSData *)masterSignature slaveSignature:(NSData *)slaveSignature;
@end

View file

@ -7,8 +7,15 @@
@implementation LKDeviceLinkMessage
- (instancetype)initInThread:(TSThread *)thread masterHexEncodedPublicKey:(NSString *)masterHexEncodedPublicKey slaveHexEncodedPublicKey:(NSString *)slaveHexEncodedPublicKey
masterSignature:(NSData *)masterSignature slaveSignature:(NSData *)slaveSignature kind:(LKDeviceLinkMessageKind)kind {
- (LKDeviceLinkMessageKind)kind {
if (self.masterSignature != nil) {
return LKDeviceLinkMessageKindAuthorization;
} else {
return LKDeviceLinkMessageKindRequest;
}
}
- (instancetype)initInThread:(TSThread *)thread masterHexEncodedPublicKey:(NSString *)masterHexEncodedPublicKey slaveHexEncodedPublicKey:(NSString *)slaveHexEncodedPublicKey masterSignature:(NSData *)masterSignature slaveSignature:(NSData *)slaveSignature {
self = [self initOutgoingMessageWithTimestamp:NSDate.ows_millisecondTimeStamp inThread:thread messageBody:@"" attachmentIds:[NSMutableArray<NSString *> new]
expiresInSeconds:0 expireStartedAt:0 isVoiceMessage:NO groupMetaMessage:TSGroupMetaMessageUnspecified quotedMessage:nil contactShare:nil linkPreview:nil];
if (self) {
@ -16,7 +23,6 @@
_slaveHexEncodedPublicKey = slaveHexEncodedPublicKey;
_masterSignature = masterSignature;
_slaveSignature = slaveSignature;
_kind = kind;
}
return self;
}
@ -27,17 +33,6 @@
[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) {

View file

@ -6,12 +6,4 @@ public extension String {
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
}
}
}

View file

@ -432,23 +432,14 @@ NS_ASSUME_NONNULL_BEGIN
if (contentProto.lokiDeviceLinkMessage != nil) {
NSString *masterHexEncodedPublicKey = contentProto.lokiDeviceLinkMessage.masterHexEncodedPublicKey;
NSString *slaveHexEncodedPublicKey = contentProto.lokiDeviceLinkMessage.slaveHexEncodedPublicKey;
NSData *masterSignature = contentProto.lokiDeviceLinkMessage.masterSignature;
NSData *slaveSignature = contentProto.lokiDeviceLinkMessage.slaveSignature;
switch (contentProto.lokiDeviceLinkMessage.type) {
case SSKProtoLokiDeviceLinkMessageTypeRequest: {
OWSLogInfo(@"[Loki] Received a device linking request from: %@", envelope.source); // Not slaveHexEncodedPublicKey
if (slaveSignature == nil) { OWSFailDebug(@"Received a device linking request from: %@ without a slave signature.", envelope.source); }
[LKDeviceLinkingSession.current processLinkingRequestFrom:slaveHexEncodedPublicKey to:masterHexEncodedPublicKey with:slaveSignature];
break;
}
case SSKProtoLokiDeviceLinkMessageTypeAuthorization: {
OWSLogInfo(@"[Loki] Received a device linking authorization from: %@", envelope.source); // Not slaveHexEncodedPublicKey
NSData *masterSignature = contentProto.lokiDeviceLinkMessage.masterSignature;
if (masterSignature == nil) { OWSFailDebug(@"Received a device linking authorization from: %@ without a master signature.", envelope.source); }
if (slaveSignature == nil) { OWSFailDebug(@"Received a device linking authorization from: %@ without a slave signature.", envelope.source); }
[LKDeviceLinkingSession.current processLinkingAuthorizationFrom:masterHexEncodedPublicKey for:slaveHexEncodedPublicKey masterSignature:masterSignature slaveSignature:slaveSignature];
break;
}
default: break;
if (masterSignature != nil) { // Authorization
OWSLogInfo(@"[Loki] Received a device linking authorization from: %@", envelope.source); // Not masterHexEncodedPublicKey
[LKDeviceLinkingSession.current processLinkingAuthorizationFrom:masterHexEncodedPublicKey for:slaveHexEncodedPublicKey masterSignature:masterSignature slaveSignature:slaveSignature];
} else if (slaveSignature != nil) { // Request
OWSLogInfo(@"[Loki] Received a device linking request from: %@", envelope.source); // Not slaveHexEncodedPublicKey }
[LKDeviceLinkingSession.current processLinkingRequestFrom:slaveHexEncodedPublicKey to:masterHexEncodedPublicKey with:slaveSignature];
}
}

View file

@ -964,30 +964,6 @@ extension SSKProtoLokiAddressMessage.SSKProtoLokiAddressMessageBuilder {
@objc public class SSKProtoLokiDeviceLinkMessage: NSObject {
// MARK: - SSKProtoLokiDeviceLinkMessageType
@objc public enum SSKProtoLokiDeviceLinkMessageType: Int32 {
case request = 1
case authorization = 2
case revocation = 3
}
private class func SSKProtoLokiDeviceLinkMessageTypeWrap(_ value: SignalServiceProtos_LokiDeviceLinkMessage.TypeEnum) -> SSKProtoLokiDeviceLinkMessageType {
switch value {
case .request: return .request
case .authorization: return .authorization
case .revocation: return .revocation
}
}
private class func SSKProtoLokiDeviceLinkMessageTypeUnwrap(_ value: SSKProtoLokiDeviceLinkMessageType) -> SignalServiceProtos_LokiDeviceLinkMessage.TypeEnum {
switch value {
case .request: return .request
case .authorization: return .authorization
case .revocation: return .revocation
}
}
// MARK: - SSKProtoLokiDeviceLinkMessageBuilder
@objc public class func builder() -> SSKProtoLokiDeviceLinkMessageBuilder {
@ -1009,9 +985,6 @@ extension SSKProtoLokiAddressMessage.SSKProtoLokiAddressMessageBuilder {
if let _value = slaveSignature {
builder.setSlaveSignature(_value)
}
if hasType {
builder.setType(type)
}
return builder
}
@ -1037,10 +1010,6 @@ extension SSKProtoLokiAddressMessage.SSKProtoLokiAddressMessageBuilder {
proto.slaveSignature = valueParam
}
@objc public func setType(_ valueParam: SSKProtoLokiDeviceLinkMessageType) {
proto.type = SSKProtoLokiDeviceLinkMessageTypeUnwrap(valueParam)
}
@objc public func build() throws -> SSKProtoLokiDeviceLinkMessage {
return try SSKProtoLokiDeviceLinkMessage.parseProto(proto)
}
@ -1092,13 +1061,6 @@ extension SSKProtoLokiAddressMessage.SSKProtoLokiAddressMessageBuilder {
return proto.hasSlaveSignature
}
@objc public var type: SSKProtoLokiDeviceLinkMessageType {
return SSKProtoLokiDeviceLinkMessage.SSKProtoLokiDeviceLinkMessageTypeWrap(proto.type)
}
@objc public var hasType: Bool {
return proto.hasType
}
private init(proto: SignalServiceProtos_LokiDeviceLinkMessage) {
self.proto = proto
}

View file

@ -528,63 +528,16 @@ struct SignalServiceProtos_LokiDeviceLinkMessage {
/// Clears the value of `slaveSignature`. Subsequent reads from it will return its default value.
mutating func clearSlaveSignature() {self._slaveSignature = nil}
var type: SignalServiceProtos_LokiDeviceLinkMessage.TypeEnum {
get {return _type ?? .request}
set {_type = newValue}
}
/// Returns true if `type` has been explicitly set.
var hasType: Bool {return self._type != nil}
/// Clears the value of `type`. Subsequent reads from it will return its default value.
mutating func clearType() {self._type = nil}
var unknownFields = SwiftProtobuf.UnknownStorage()
enum TypeEnum: SwiftProtobuf.Enum {
typealias RawValue = Int
case request // = 1
case authorization // = 2
case revocation // = 3
init() {
self = .request
}
init?(rawValue: Int) {
switch rawValue {
case 1: self = .request
case 2: self = .authorization
case 3: self = .revocation
default: return nil
}
}
var rawValue: Int {
switch self {
case .request: return 1
case .authorization: return 2
case .revocation: return 3
}
}
}
init() {}
fileprivate var _masterHexEncodedPublicKey: String? = nil
fileprivate var _slaveHexEncodedPublicKey: String? = nil
fileprivate var _masterSignature: Data? = nil
fileprivate var _slaveSignature: Data? = nil
fileprivate var _type: SignalServiceProtos_LokiDeviceLinkMessage.TypeEnum? = nil
}
#if swift(>=4.2)
extension SignalServiceProtos_LokiDeviceLinkMessage.TypeEnum: CaseIterable {
// Support synthesized by the compiler.
}
#endif // swift(>=4.2)
struct SignalServiceProtos_CallMessage {
// SwiftProtobuf.Message conformance is added in an extension below. See the
// `Message` and `Message+*Additions` files in the SwiftProtobuf library for
@ -3032,7 +2985,6 @@ extension SignalServiceProtos_LokiDeviceLinkMessage: SwiftProtobuf.Message, Swif
2: .same(proto: "slaveHexEncodedPublicKey"),
3: .same(proto: "masterSignature"),
4: .same(proto: "slaveSignature"),
5: .same(proto: "type"),
]
mutating func decodeMessage<D: SwiftProtobuf.Decoder>(decoder: inout D) throws {
@ -3042,7 +2994,6 @@ extension SignalServiceProtos_LokiDeviceLinkMessage: SwiftProtobuf.Message, Swif
case 2: try decoder.decodeSingularStringField(value: &self._slaveHexEncodedPublicKey)
case 3: try decoder.decodeSingularBytesField(value: &self._masterSignature)
case 4: try decoder.decodeSingularBytesField(value: &self._slaveSignature)
case 5: try decoder.decodeSingularEnumField(value: &self._type)
default: break
}
}
@ -3061,9 +3012,6 @@ extension SignalServiceProtos_LokiDeviceLinkMessage: SwiftProtobuf.Message, Swif
if let v = self._slaveSignature {
try visitor.visitSingularBytesField(value: v, fieldNumber: 4)
}
if let v = self._type {
try visitor.visitSingularEnumField(value: v, fieldNumber: 5)
}
try unknownFields.traverse(visitor: &visitor)
}
@ -3072,20 +3020,11 @@ extension SignalServiceProtos_LokiDeviceLinkMessage: SwiftProtobuf.Message, Swif
if lhs._slaveHexEncodedPublicKey != rhs._slaveHexEncodedPublicKey {return false}
if lhs._masterSignature != rhs._masterSignature {return false}
if lhs._slaveSignature != rhs._slaveSignature {return false}
if lhs._type != rhs._type {return false}
if lhs.unknownFields != rhs.unknownFields {return false}
return true
}
}
extension SignalServiceProtos_LokiDeviceLinkMessage.TypeEnum: SwiftProtobuf._ProtoNameProviding {
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "REQUEST"),
2: .same(proto: "AUTHORIZATION"),
3: .same(proto: "REVOCATION"),
]
}
extension SignalServiceProtos_CallMessage: SwiftProtobuf.Message, SwiftProtobuf._MessageImplementationBase, SwiftProtobuf._ProtoNameProviding {
static let protoMessageName: String = _protobuf_package + ".CallMessage"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [