diff --git a/SignalServiceKit/src/Loki/API/LokiGroupChatAPI.swift b/SignalServiceKit/src/Loki/API/LokiGroupChatAPI.swift index 5309235d9..b2b73a98f 100644 --- a/SignalServiceKit/src/Loki/API/LokiGroupChatAPI.swift +++ b/SignalServiceKit/src/Loki/API/LokiGroupChatAPI.swift @@ -13,25 +13,41 @@ public final class LokiGroupChatAPI : NSObject { return SSKEnvironment.shared.contactsManager.displayName(forPhoneIdentifier: userHexEncodedPublicKey) ?? "Anonymous" } + internal static var identityKeyPair: ECKeyPair { + return OWSIdentityManager.shared().identityKeyPair()! + } + private static var userHexEncodedPublicKey: String { - return OWSIdentityManager.shared().identityKeyPair()!.hexEncodedPublicKey + return identityKeyPair.hexEncodedPublicKey } + public enum Error : Swift.Error { - case tokenParsingFailed, messageParsingFailed + case tokenParsingFailed, tokenDecryptionFailed, messageParsingFailed } - public static func getEncryptedToken() -> Promise { + public static func fetchToken() -> Promise { print("[Loki] Getting group chat auth token.") - let url = URL(string: "\(serverURL)/loki/v1/getToken")! - let parameters = [ "pubKey" : userHexEncodedPublicKey ] - let request = TSRequest(url: url, method: "POST", parameters: parameters) + let url = URL(string: "\(serverURL)/loki/v1/get_challenge?pubKey=\(userHexEncodedPublicKey)")! + let request = TSRequest(url: url) return TSNetworkManager.shared().makePromise(request: request).map { $0.responseObject }.map { rawResponse in - guard let json = rawResponse as? JSON, let encryptedToken = json["cipherText64"] as? String else { throw Error.tokenParsingFailed } - return encryptedToken + guard let json = rawResponse as? JSON, let cipherText64 = json["cipherText64"] as? String, let nonce64 = json["nonce64"] as? String, let serverPubKey64 = json["serverPubKey64"] as? String, let cipherText = Data(base64Encoded: cipherText64), let nonce = Data(base64Encoded: nonce64), let serverPubKey = Data(base64Encoded: serverPubKey64) else { throw Error.tokenParsingFailed } + + let ivAndCipher = nonce + cipherText + guard let tokenData = try? DiffieHellman.decrypt(cipherText: ivAndCipher, publicKey: serverPubKey, privateKey: identityKeyPair.privateKey) else { throw Error.tokenDecryptionFailed } + + return tokenData.base64EncodedString() } } + public static func submitToken(_ token: String) -> Promise { + print("[Loki] Submitting group chat auth token.") + let url = URL(string: "\(serverURL)/loki/v1/submit_challenge")! + let parameters = [ "pubKey" : userHexEncodedPublicKey, "token" : token ] + let request = TSRequest(url: url, method: "POST", parameters: parameters) + return TSNetworkManager.shared().makePromise(request: request).asVoid() + } + public static func getMessages(for group: UInt) -> Promise<[LokiGroupMessage]> { print("[Loki] Getting messages for group chat with ID: \(group).") let queryParameters = "include_annotations=1&count=-\(batchCount)" diff --git a/SignalServiceKit/src/Loki/Crypto/FallbackSessionCipher.swift b/SignalServiceKit/src/Loki/Crypto/FallbackSessionCipher.swift index 336bdc4a6..e1d92c587 100644 --- a/SignalServiceKit/src/Loki/Crypto/FallbackSessionCipher.swift +++ b/SignalServiceKit/src/Loki/Crypto/FallbackSessionCipher.swift @@ -72,7 +72,7 @@ private extension String { @objc public func encrypt(message: Data) -> Data? { guard let symmetricKey = symmetricKey else { return nil } do { - return try diffieHellmanEncrypt(plainText: message, symmetricKey: symmetricKey) + return try DiffieHellman.encrypt(plainText: message, symmetricKey: symmetricKey) } catch { Logger.warn("FallBackSessionCipher: Failed to encrypt message") return nil @@ -86,38 +86,10 @@ private extension String { @objc public func decrypt(message: Data) -> Data? { guard let symmetricKey = symmetricKey else { return nil } do { - return try diffieHellmanDecrypt(cipherText: message, symmetricKey: symmetricKey) + return try DiffieHellman.decrypt(cipherText: message, symmetricKey: symmetricKey) } catch { Logger.warn("FallBackSessionCipher: Failed to decrypt message") return nil } } - - // Encypt the message with the symmetric key and a 16 bit iv - private func diffieHellmanEncrypt(plainText: Data, symmetricKey: Data) throws -> Data { - let iv = Randomness.generateRandomBytes(ivLength)! - let ivBytes = [UInt8](iv) - - let symmetricKeyBytes = [UInt8](symmetricKey) - let messageBytes = [UInt8](plainText) - - let blockMode = CBC(iv: ivBytes) - let aes = try AES(key: symmetricKeyBytes, blockMode: blockMode) - let cipherText = try aes.encrypt(messageBytes) - let ivAndCipher = ivBytes + cipherText - return Data(bytes: ivAndCipher, count: ivAndCipher.count) - } - - // Decrypt the message with the symmetric key - private func diffieHellmanDecrypt(cipherText: Data, symmetricKey: Data) throws -> Data { - let symmetricKeyBytes = [UInt8](symmetricKey) - let ivBytes = [UInt8](cipherText[..