From 9c9049774ed20f151cc67ae2908d291599ff6427 Mon Sep 17 00:00:00 2001 From: gmbnt Date: Thu, 2 Apr 2020 09:53:03 +1100 Subject: [PATCH] Add more documentation --- .../OnionRequestAPI+Encryption.swift | 2 +- .../API/Onion Requests/OnionRequestAPI.swift | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI+Encryption.swift b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI+Encryption.swift index 1fc7d232f..563fa0004 100644 --- a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI+Encryption.swift +++ b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI+Encryption.swift @@ -60,7 +60,7 @@ extension OnionRequestAPI { return promise } - /// Encrypts the previous encryption result (i.e. that of the hop after this one) for the given hop. Use this to build the layers of an onion request. + /// Encrypts the previous encryption result (i.e. that of the hop after this one) for this hop. Use this to build the layers of an onion request. internal static func encryptHop(from snode1: LokiAPITarget, to snode2: LokiAPITarget, using previousEncryptionResult: EncryptionResult) -> Promise { let (promise, seal) = Promise.pending() getQueue().async { diff --git a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift index 408524a83..146ed3c09 100644 --- a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift +++ b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift @@ -12,7 +12,7 @@ internal enum OnionRequestAPI { internal static let workQueue = DispatchQueue(label: "OnionRequestAPI.workQueue", qos: .userInitiated) // MARK: Settings - private static let pathCount: UInt = 3 + private static let pathCount: UInt = 2 /// The number of snodes (including the guard snode) in a path. private static let pathSize: UInt = 3 private static let timeout: TimeInterval = 20 @@ -65,7 +65,7 @@ internal enum OnionRequestAPI { internal typealias Path = [LokiAPITarget] // MARK: Onion Building Result - private typealias OnionBuildingResult = (guardSnode: LokiAPITarget, encryptionResult: EncryptionResult, symmetricKey: Data) + private typealias OnionBuildingResult = (guardSnode: LokiAPITarget, encryptionResult: EncryptionResult, targetSnodeSymmetricKey: Data) // MARK: Private API private static func execute(_ verb: HTTPVerb, _ url: String, parameters: JSON? = nil, timeout: TimeInterval = OnionRequestAPI.timeout) -> Promise { @@ -217,13 +217,15 @@ internal enum OnionRequestAPI { /// Builds an onion around `payload` and returns the result. private static func buildOnion(around payload: Data, targetedAt snode: LokiAPITarget) -> Promise { var guardSnode: LokiAPITarget! + var targetSnodeSymmetricKey: Data! // Needed by invoke(_:on:with:) to decrypt the response sent back by the target snode var encryptionResult: EncryptionResult! - var symmetricKey: Data! return getPath().then(on: workQueue) { path -> Promise in guardSnode = path.first! + // Encrypt in reverse order, i.e. the target snode first return encrypt(payload, forTargetSnode: snode).then(on: workQueue) { r -> Promise in + targetSnodeSymmetricKey = r.symmetricKey + // Recursively encrypt the layers of the onion (again in reverse order) encryptionResult = r - symmetricKey = r.symmetricKey var path = path var rhs = snode func addLayer() -> Promise { @@ -240,12 +242,12 @@ internal enum OnionRequestAPI { } return addLayer() } - }.map(on: workQueue) { _ in (guardSnode: guardSnode, encryptionResult: encryptionResult, symmetricKey: symmetricKey) } + }.map(on: workQueue) { _ in (guardSnode, encryptionResult, targetSnodeSymmetricKey) } } // MARK: Internal API /// Sends an onion request to `snode`. Builds new paths as needed. - internal static func invoke(_ method: LokiAPITarget.Method, on snode: LokiAPITarget, parameters: JSON) -> Promise { + internal static func invoke(_ method: LokiAPITarget.Method, on snode: LokiAPITarget, with parameters: JSON) -> Promise { let (promise, seal) = Promise.pending() workQueue.async { let parameters: JSON = [ "method" : method.rawValue, "params" : parameters ] @@ -265,7 +267,7 @@ internal enum OnionRequestAPI { "ciphertext" : onion.base64EncodedString(), "ephemeral_key" : encryptionResult.ephemeralPublicKey.toHexString() ] - let symmetricKey = intermediate.symmetricKey + let targetSnodeSymmetricKey = intermediate.targetSnodeSymmetricKey execute(.post, url, parameters: parameters).done(on: workQueue) { rawResponse in guard let json = rawResponse as? JSON, let base64EncodedIVAndCiphertext = json["result"] as? String, let ivAndCiphertext = Data(base64Encoded: base64EncodedIVAndCiphertext) else { return seal.reject(Error.invalidJSON) } @@ -273,7 +275,7 @@ internal enum OnionRequestAPI { let ciphertext = ivAndCiphertext[Int(ivSize)...] do { let gcm = GCM(iv: iv.bytes, tagLength: Int(gcmTagSize), mode: .combined) - let aes = try AES(key: symmetricKey.bytes, blockMode: gcm, padding: .pkcs7) + let aes = try AES(key: targetSnodeSymmetricKey.bytes, blockMode: gcm, padding: .pkcs7) let result = try aes.decrypt(ciphertext.bytes) seal.fulfill(Data(bytes: result)) } catch (let error) {