diff --git a/ConversationsClassic/AppData/Client/Client.swift b/ConversationsClassic/AppData/Client/Client.swift index 40a0331..d355b05 100644 --- a/ConversationsClassic/AppData/Client/Client.swift +++ b/ConversationsClassic/AppData/Client/Client.swift @@ -110,31 +110,25 @@ extension Client { func uploadFile(_ localURL: URL) async throws -> String { // get data from file - guard let data = try? Data(contentsOf: localURL) else { + guard var data = try? Data(contentsOf: localURL) else { throw AppError.noData } - // encode data with AES_GSM - guard let iv = try? AESGSMEngine.generateIV(), let key = try? AESGSMEngine.generateKey() else { - throw AppError.securityError - } - var encodedData = Data() - var tag = Data() - guard AESGSMEngine.shared.encrypt(iv: iv, key: key, message: data, output: &encodedData, tag: &tag) else { - throw AppError.securityError - } + // encrypt data if needed + let ((key, iv), encrypted) = try await encryptFile(data) + data = encrypted // upload let httpModule = connection.module(HttpFileUploadModule.self) let components = try await httpModule.findHttpUploadComponents() - guard let component = components.first(where: { $0.maxSize > encodedData.count }) else { + guard let component = components.first(where: { $0.maxSize > data.count }) else { throw AppError.fileTooBig } let slot = try await httpModule.requestUploadSlot( componentJid: component.jid, filename: localURL.lastPathComponent, - size: encodedData.count, + size: data.count, contentType: localURL.mimeType ) var request = URLRequest(url: slot.putUri) @@ -142,8 +136,8 @@ extension Client { request.addValue(value, forHTTPHeaderField: key) } request.httpMethod = "PUT" - request.httpBody = encodedData - request.addValue(String(encodedData.count), forHTTPHeaderField: "Content-Length") + request.httpBody = data + request.addValue(String(data.count), forHTTPHeaderField: "Content-Length") request.addValue(localURL.mimeType, forHTTPHeaderField: "Content-Type") let (_, response) = try await URLSession.shared.data(for: request) switch response { @@ -198,6 +192,19 @@ private extension Client { }) } } + + func encryptFile(_ data: Data) async throws -> ((Data, Data), Data) { + guard let iv = try? AESGSMEngine.generateIV(), let key = try? AESGSMEngine.generateKey() else { + throw AppError.securityError + } + var encrypted = Data() + var tag = Data() + guard AESGSMEngine.shared.encrypt(iv: iv, key: key, message: data, output: &encrypted, tag: &tag) else { + throw AppError.securityError + } + + return ((key, iv), encrypted) + } } extension Client {