How would you approach an Encryption Key being leaked?

I was curious as to the procedure for having an encryption key leaked and was hoping to have your opinions on how these two questions will be answered [if you were in the position].

Q1: Let's say, for instance, that you're making a social media network that stores private messages in a database network (such as Firebase) and uses basic encryption to store that data into an encrypted format (e.g., text message: "Hello Mous772!"; Firebase data: "deaErG5gao7J5qw/QI3EOA==").

But oh no! Someone got access to the encryption key used to encrypt hundreds of thousands of messages. You cannot simply delete thousands of messages because of this hacker, so how should you deal with this? This is where my question comes in. Is it possible to change the encryption key for all of the data if I am using the code system at the bottom of this question and using that code system to store encrypted data in Firebase? If so, how would you go about doing that? (Please use simple language; I'm not good with this stuff).

Q2: What, in your opinion, is the best way to prevent this in the first place? I was told that a good solution was to store two sets of the same data; when one kegs it, we shut down the original and use the backup; however, this does not sound sustainable at all. I want to know what steps can be taken to ensure this never happens.

[Please don't give me "Well... you can never *really hide these keys!" I'm well aware it's not possible to never have them leaked ever; I'm just looking for best practices only.]

This is the encryption system we are using for this hypothetical app.


// MARK: Value 
// MARK: Private

private let key: Data
private let iv: Data


// MARK: - Initialzier
init?(key: String, iv: String) {
    guard key.count == kCCKeySizeAES128 || key.count == kCCKeySizeAES256, let keyData = key.data(using: .utf8) else {
        debugPrint("Error: Failed to set a key.")
        return nil
    }

    guard iv.count == kCCBlockSizeAES128, let ivData = iv.data(using: .utf8) else {
        debugPrint("Error: Failed to set an initial vector.")
        return nil
    }


    self.key = keyData
    self.iv  = ivData
}


// MARK: - Function
// MARK: Public
func encrypt(string: String) -> Data? {
    return crypt(data: string.data(using: .utf8), option: CCOperation(kCCEncrypt))
}

func decrypt(data: Data?) -> String? {
    guard let decryptedData = crypt(data: data, option: CCOperation(kCCDecrypt)) else { return nil }
    return String(bytes: decryptedData, encoding: .utf8)
}

func crypt(data: Data?, option: CCOperation) -> Data? {
    guard let data = data else { return nil }

    let cryptLength = data.count + key.count
    var cryptData   = Data(count: cryptLength)

    var bytesLength = Int(0)

    let status = cryptData.withUnsafeMutableBytes { cryptBytes in
        data.withUnsafeBytes { dataBytes in
            iv.withUnsafeBytes { ivBytes in
                key.withUnsafeBytes { keyBytes in
                CCCrypt(option, CCAlgorithm(kCCAlgorithmAES), CCOptions(kCCOptionPKCS7Padding), keyBytes.baseAddress, key.count, ivBytes.baseAddress, dataBytes.baseAddress, data.count, cryptBytes.baseAddress, cryptLength, &bytesLength)
                }
            }
        }
    }

    guard Int32(status) == Int32(kCCSuccess) else {
        debugPrint("Error: Failed to crypt data. Status \(status)")
        return nil
    }

    cryptData.removeSubrange(bytesLength..<cryptData.count)
    return cryptData
}
}

//let password = "UserPassword1!"
//let key128   = "1234567890123456"                   // 16 bytes for AES128
//let key256   = "12345678901234561234567890123456"   // 32 bytes for AES256
//let iv       = "abcdefghijklmnop"                   // 16 bytes for AES128

//let aes128 = AES(key: key128, iv: iv)
//let aes256 = AES(key: key256, iv: iv)

//let encryptedPassword128 = aes128?.encrypt(string: password)
//aes128?.decrypt(data: encryptedPassword128)

//let encryptedPassword256 = aes256?.encrypt(string: password)
//aes256?.decrypt(data: encryptedPassword256)

Also (sorry this is not in the question) if it is possible to change the encryption key, what if someone else changes it and locks me out?

This stuff is all very complicated and hard to get right. Your code appears to show a single hard-coded key embedded in the app; this is absolutely wrong.

Don’t ever try to invent your own encryption scheme. (That doesn’t just mean your own encryption algorithm, but also all the supporting stuff like when you generate keys, how you distribute them etc.) Investigate the state-of-the-art and implement that, carefully.

But first, ask yourself what your threat model is. What, exactly, are you trying to prevent by adding encryption to your system?

Don't follow these apps' example:

"Millions of Android and iOS users at risk from hardcoded creds in popular apps" - https://www.theregister.com/2024/10/23/android_ios_security/

How would you approach an Encryption Key being leaked?
 
 
Q