iOS how to decrypt an encrypted large file?


This may not be an iOS question – logic from other platforms could probably apply here too.

On iPhone, I am successfully able to encrypt and decrypt data such as String, UIImage etc. using CryptoKit as following:

import CryptoKit

do {
    
    let alicePrivateKey = P521.KeyAgreement.PrivateKey()
    let bobPrivateKey = P521.KeyAgreement.PrivateKey()
    let alicePublicKey = alicePrivateKey.publicKey
    let bobPublicKey = bobPrivateKey.publicKey
    
    let shared_secret_alice = try alicePrivateKey.sharedSecretFromKeyAgreement(with: bobPublicKey)
    let shared_secret_bob = try bobPrivateKey.sharedSecretFromKeyAgreement(with: alicePublicKey)
    
    guard shared_secret_alice == shared_secret_bob else {
        throw "Shared secret isn't the same between Alice and Bob"
    }
    
    guard let dataToSend = UIImage(named: "image")?.jpegData(compressionQuality: 1) else {
        return
    }
    
    print("original decrypted: \(dataToSend.hex())")
    
    let alice_key = shared_secret_alice.x963DerivedSymmetricKey(using: SHA512.self , sharedInfo: Data(), outputByteCount: 16)
    let encrypted = try encryptedData(decryptedData: dataToSend, key: alice_key)
    
    print("encrypted: \(encrypted.hex())")
    
    let bobs_key = shared_secret_bob.x963DerivedSymmetricKey(using: SHA512.self , sharedInfo: Data(), outputByteCount: 16)
    
    let decryptedAgain = try decryptData(encryptedData: encrypted, key: bobs_key)
            
    print("decrypted again: \(decryptedAgain.hex())")
    
    print("decrypted is same as original decrypted?: \(dataToSend.hex() == decryptedAgain.hex())")
    
    guard let decryptedImage = UIImage(data: decryptedAgain) else {
        return
    }
    
    print("decryptedImage: \(decryptedImage)")
    
} catch {
    print("Error encrypting: \(error)")
}

func encryptedData(decryptedData : Data, key : SymmetricKey) throws -> Data {
    let sealedMessage = try AES.GCM.seal(decryptedData, using: key)
    
    guard let encryptedData = sealedMessage.combined else {
        throw "Error in sealedMessage"
    }
    
    return encryptedData
}

func decryptData(encryptedData : Data, key : SymmetricKey) throws -> Data {
    
    let sealedBoxRecreated = try AES.GCM.SealedBox(combined: encryptedData)
    
    return try AES.GCM.open(sealedBoxRecreated, using: key);
}

extension String: LocalizedError {
    public var errorDescription: String? { return self }
}

extension Data {
    func hex() -> String {
        return String(map { String(format: "%02hhx", $0) }.joined().prefix(20)) + "..."
    }
}

My problem is that the above works okay for small images or strings but for images/videos/files of larger size, it requires me to load the entire data in memory to encrypt and decrypt. This would quickly run out of memory for larger files. So I am looking for a better solution which doesn’t require loading the entire thing in memory.

I did find the following questions:

IOS – How do I AES decrypt a large file if the file is too large to load all of it into memory?

AES encrypting large files in iOS

But these are from 2012 which is long before modern CryptoKit became available.

  1. Is there some newer way this came be done effectively?

  2. I understand the concept of breaking the data into smaller chunks, reading the smaller chunks, encrypting them, appending them to a new location. However, I am not sure how to decrypt it afterwards? What I am confused about is – in the final file which is the appended encrypted chunks, how should I determine each individual encrypted chunk to decrypt?

For example:

Lets say original file is 123456

I break this down into 6 chunks: 1, 2, 3, 4, 5, 6

I encrypt each of these chunks: hf1d, cd2, 12dm, 7d3, 55gr, 61w3d

I append them all to create the combined file: hf1dcd212dm7d355gr61w3d

Now I need to decrypt this combined file.

  1. How should I break it down into each chunk for decryption? As far as I am aware, the encrypted chunks can vary in length.

Or am I very wrong in my logic?

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img