diff --git a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI+Encryption.swift b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI+Encryption.swift index 563fa0004..bae219de8 100644 --- a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI+Encryption.swift +++ b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI+Encryption.swift @@ -44,13 +44,16 @@ extension OnionRequestAPI { } /// Encrypts `payload` for `snode` and returns the result. Use this to build the core of an onion request. - internal static func encrypt(_ payload: Data, forTargetSnode snode: LokiAPITarget) -> Promise { + internal static func encrypt(_ payload: JSON, forTargetSnode snode: LokiAPITarget) -> Promise { let (promise, seal) = Promise.pending() getQueue().async { - let parameters: JSON = [ "body" : payload.base64EncodedString(), "headers" : "" ] do { - guard JSONSerialization.isValidJSONObject(parameters) else { return seal.reject(Error.invalidJSON) } - let plaintext = try JSONSerialization.data(withJSONObject: parameters, options: []) + guard JSONSerialization.isValidJSONObject(payload) else { return seal.reject(Error.invalidJSON) } + let payloadAsData = try JSONSerialization.data(withJSONObject: payload, options: []) + let payloadAsString = String(data: payloadAsData, encoding: .utf8)! // Snodes only accept this as a string + let wrapper: JSON = [ "body" : payloadAsString, "headers" : "" ] + guard JSONSerialization.isValidJSONObject(wrapper) else { return seal.reject(Error.invalidJSON) } + let plaintext = try JSONSerialization.data(withJSONObject: wrapper, options: []) let result = try encrypt(plaintext, forSnode: snode) seal.fulfill(result) } catch (let error) { diff --git a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift index 146ed3c09..c9c7a9751 100644 --- a/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift +++ b/SignalServiceKit/src/Loki/API/Onion Requests/OnionRequestAPI.swift @@ -65,7 +65,7 @@ internal enum OnionRequestAPI { internal typealias Path = [LokiAPITarget] // MARK: Onion Building Result - private typealias OnionBuildingResult = (guardSnode: LokiAPITarget, encryptionResult: EncryptionResult, targetSnodeSymmetricKey: Data) + private typealias OnionBuildingResult = (guardSnode: LokiAPITarget, finalEncryptionResult: EncryptionResult, targetSnodeSymmetricKey: Data) // MARK: Private API private static func execute(_ verb: HTTPVerb, _ url: String, parameters: JSON? = nil, timeout: TimeInterval = OnionRequestAPI.timeout) -> Promise { @@ -215,7 +215,7 @@ internal enum OnionRequestAPI { } /// Builds an onion around `payload` and returns the result. - private static func buildOnion(around payload: Data, targetedAt snode: LokiAPITarget) -> Promise { + private static func buildOnion(around payload: JSON, 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! @@ -250,22 +250,15 @@ internal enum OnionRequestAPI { 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 ] - let payload: Data - do { - guard JSONSerialization.isValidJSONObject(parameters) else { return seal.reject(Error.invalidJSON) } - payload = try JSONSerialization.data(withJSONObject: parameters, options: []) - } catch (let error) { - return seal.reject(error) - } + let payload: JSON = [ "method" : method.rawValue, "params" : parameters ] buildOnion(around: payload, targetedAt: snode).done(on: workQueue) { intermediate in let guardSnode = intermediate.guardSnode let url = "\(guardSnode.address):\(guardSnode.port)/onion_req" - let encryptionResult = intermediate.encryptionResult - let onion = encryptionResult.ciphertext + let finalEncryptionResult = intermediate.finalEncryptionResult + let onion = finalEncryptionResult.ciphertext let parameters: JSON = [ "ciphertext" : onion.base64EncodedString(), - "ephemeral_key" : encryptionResult.ephemeralPublicKey.toHexString() + "ephemeral_key" : finalEncryptionResult.ephemeralPublicKey.toHexString() ] let targetSnodeSymmetricKey = intermediate.targetSnodeSymmetricKey execute(.post, url, parameters: parameters).done(on: workQueue) { rawResponse in