From 0b0f0a37870c47e89f3479148bd8a6a1ea8b6bfb Mon Sep 17 00:00:00 2001 From: Ryan Zhao Date: Mon, 2 May 2022 11:35:48 +1000 Subject: [PATCH] retrieve messages authenticated for 1-1 chats --- .../Pollers/ClosedGroupPoller.swift | 2 +- SessionSnodeKit/SnodeAPI.swift | 52 +++++++++++++++---- 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift b/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift index 481a9b336..ade1badd4 100644 --- a/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift +++ b/SessionMessagingKit/Sending & Receiving/Pollers/ClosedGroupPoller.swift @@ -103,7 +103,7 @@ public final class ClosedGroupPoller : NSObject { // randomElement() uses the system's default random generator, which is cryptographically secure guard let snode = swarm.randomElement() else { return Promise(error: Error.insufficientSnodes) } guard let self = self, self.isPolling(for: groupPublicKey) else { return Promise(error: Error.pollingCanceled) } - return SnodeAPI.getRawMessages(from: snode, associatedWith: groupPublicKey).map2 { + return SnodeAPI.getRawMessagesUnauthenticated(from: snode, associatedWith: groupPublicKey).map2 { let (rawMessages, lastRawMessage) = SnodeAPI.parseRawMessagesResponse($0, from: snode, associatedWith: groupPublicKey) return (snode, rawMessages, lastRawMessage) diff --git a/SessionSnodeKit/SnodeAPI.swift b/SessionSnodeKit/SnodeAPI.swift index ae1382e67..7e957f72c 100644 --- a/SessionSnodeKit/SnodeAPI.swift +++ b/SessionSnodeKit/SnodeAPI.swift @@ -22,6 +22,11 @@ public final class SnodeAPI : NSObject { public static var clockOffset: Int64 = 0 /// - Note: Should only be accessed from `Threading.workQueue` to avoid race conditions. public static var swarmCache: [String:Set] = [:] + + // MARK: Namespaces + private static let defaultNamespace = 0 + private static let unauthenticatedNamespace = -10 + private static let configNamespace = 5 // MARK: Settings private static let maxRetryCount: UInt = 8 @@ -391,36 +396,61 @@ public final class SnodeAPI : NSObject { } public static func getRawMessages(from snode: Snode, associatedWith publicKey: String) -> RawResponsePromise { + let (promise, seal) = RawResponsePromise.pending() + Threading.workQueue.async { + getMessagesWithAuthentication(from: snode, associatedWith: publicKey).done2 { seal.fulfill($0) }.catch2 { seal.reject($0) } + } + return promise + } + + public static func getRawMessagesUnauthenticated(from snode: Snode, associatedWith publicKey: String) -> RawResponsePromise { let (promise, seal) = RawResponsePromise.pending() Threading.workQueue.async { getMessagesInternal(from: snode, associatedWith: publicKey).done2 { seal.fulfill($0) }.catch2 { seal.reject($0) } } return promise } - - private static func getMessagesInternal(from snode: Snode, associatedWith publicKey: String) -> RawResponsePromise { + + private static func getMessagesWithAuthentication(from snode: Snode, associatedWith publicKey: String) -> RawResponsePromise { let storage = SNSnodeKitConfiguration.shared.storage - // NOTE: All authentication logic is currently commented out, the reason being that we can't currently support + // NOTE: All authentication logic is only apply to 1-1 chats, the reason being that we can't currently support // it yet for closed groups. The Storage Server requires an ed25519 key pair, but we don't have that for our // closed groups. -// guard let userED25519KeyPair = storage.getUserED25519KeyPair() else { return Promise(error: Error.noKeyPair) } + guard let userED25519KeyPair = storage.getUserED25519KeyPair() else { return Promise(error: Error.noKeyPair) } // Get last message hash storage.pruneLastMessageHashInfoIfExpired(for: snode, associatedWith: publicKey) let lastHash = storage.getLastMessageHash(for: snode, associatedWith: publicKey) ?? "" // Construct signature -// let timestamp = UInt64(Int64(NSDate.millisecondTimestamp()) + SnodeAPI.clockOffset) -// let ed25519PublicKey = userED25519KeyPair.publicKey.toHexString() -// let verificationData = ("retrieve" + String(timestamp)).data(using: String.Encoding.utf8)! -// let signature = sodium.sign.signature(message: Bytes(verificationData), secretKey: userED25519KeyPair.secretKey)! + let timestamp = UInt64(Int64(NSDate.millisecondTimestamp()) + SnodeAPI.clockOffset) + let ed25519PublicKey = userED25519KeyPair.publicKey.toHexString() + let verificationData = ("retrieve" + String(timestamp)).data(using: String.Encoding.utf8)! + let signature = sodium.sign.signature(message: Bytes(verificationData), secretKey: userED25519KeyPair.secretKey)! + // Make the request + let parameters: JSON = [ + "pubKey" : Features.useTestnet ? publicKey.removing05PrefixIfNeeded() : publicKey, + "namespace": defaultNamespace, + "lastHash" : lastHash, + "timestamp" : timestamp, + "pubkey_ed25519" : ed25519PublicKey, + "signature" : signature.toBase64() + ] + return invoke(.getMessages, on: snode, associatedWith: publicKey, parameters: parameters) + } + + private static func getMessagesInternal(from snode: Snode, associatedWith publicKey: String) -> RawResponsePromise { + let storage = SNSnodeKitConfiguration.shared.storage + + // Get last message hash + storage.pruneLastMessageHashInfoIfExpired(for: snode, associatedWith: publicKey) + let lastHash = storage.getLastMessageHash(for: snode, associatedWith: publicKey) ?? "" + // Make the request let parameters: JSON = [ "pubKey" : Features.useTestnet ? publicKey.removing05PrefixIfNeeded() : publicKey, + "namespace": unauthenticatedNamespace, "lastHash" : lastHash, -// "timestamp" : timestamp, -// "pubkey_ed25519" : ed25519PublicKey, -// "signature" : signature.toBase64()! ] return invoke(.getMessages, on: snode, associatedWith: publicKey, parameters: parameters) }