another.im-ios/ConversationsClassic/AppData/Services/AESGSMEngine.swift
2024-09-08 18:27:08 +02:00

66 lines
2.2 KiB
Swift

import CryptoKit
import Foundation
import MartinOMEMO
final class AESGSMEngine: AES_GCM_Engine {
static let shared = AESGSMEngine()
private init() {}
func encrypt(iv: Data, key: Data, message: Data, output: UnsafeMutablePointer<Data>?, tag: UnsafeMutablePointer<Data>?) -> Bool {
do {
let symmetricKey = SymmetricKey(data: key)
let sealedBox = try AES.GCM.seal(message, using: symmetricKey, nonce: AES.GCM.Nonce(data: iv))
if let output = output, let data = sealedBox.combined {
output.pointee = data
}
if let tag = tag {
tag.pointee = sealedBox.tag
}
return true
} catch {
print("Encryption error: \(error)")
return false
}
}
func decrypt(iv: Data, key: Data, encoded: Data, auth tag: Data?, output: UnsafeMutablePointer<Data>?) -> Bool {
do {
let symmetricKey = SymmetricKey(data: key)
let sealedBox: AES.GCM.SealedBox
if let tag {
sealedBox = try AES.GCM.SealedBox(nonce: AES.GCM.Nonce(data: iv), ciphertext: encoded, tag: tag)
} else {
let embeddedTag = encoded.subdata(in: (encoded.count - 16) ..< encoded.count)
let payload = encoded.subdata(in: 0 ..< (encoded.count - 16))
sealedBox = try AES.GCM.SealedBox(nonce: AES.GCM.Nonce(data: iv), ciphertext: payload, tag: embeddedTag)
}
let decryptedData = try AES.GCM.open(sealedBox, using: symmetricKey)
if let output = output {
output.pointee = decryptedData
}
return true
} catch {
print("Decryption error: \(error)")
return false
}
}
static func generateIV() throws -> Data {
var bytes = [Int8](repeating: 0, count: 12)
let status = SecRandomCopyBytes(kSecRandomDefault, bytes.count, &bytes)
if status != errSecSuccess {
throw AppError.securityError
}
return Data(bytes: bytes, count: bytes.count)
}
static func generateKey() throws -> Data {
let key = SymmetricKey(size: .bits256)
return key.withUnsafeBytes { Data($0) }
}
}