Leveraging iOS Data Protection

Leveraging iOS Data Protection

iOS provides powerful data protection mechanisms that automatically encrypt files when devices are locked. Understanding and properly implementing these features is crucial for protecting user data.

Data Protection Classes:

// Implementing different data protection levels
import UIKit

class DataProtectionManager {
    
    // Most secure - file is only accessible when device is unlocked
    func saveHighlySensitiveData(_ data: Data, to filename: String) throws {
        let documentsPath = FileManager.default.urls(for: .documentDirectory, 
                                                     in: .userDomainMask).first!
        let fileURL = documentsPath.appendingPathComponent(filename)
        
        try data.write(to: fileURL, options: [.atomic, .completeFileProtection])
    }
    
    // Accessible after first unlock until reboot
    func saveModerateSensitiveData(_ data: Data, to filename: String) throws {
        let documentsPath = FileManager.default.urls(for: .documentDirectory, 
                                                     in: .userDomainMask).first!
        let fileURL = documentsPath.appendingPathComponent(filename)
        
        try data.write(to: fileURL, options: [.atomic, .completeFileProtectionUntilFirstUserAuthentication])
    }
    
    // Setting protection level for existing files
    func updateFileProtection(for fileURL: URL) throws {
        try FileManager.default.setAttributes(
            [.protectionKey: FileProtectionType.complete],
            ofItemAtPath: fileURL.path
        )
    }
}

Core Data Encryption:

// Configuring Core Data with encryption
import CoreData

class SecureCoreDataStack {
    lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "DataModel")
        
        // Configure for encryption
        let storeDescription = container.persistentStoreDescriptions.first
        storeDescription?.setOption(FileProtectionType.complete.rawValue, 
                                   forKey: NSPersistentStoreFileProtectionKey)
        
        // Enable encryption at rest
        storeDescription?.setOption(true, 
                                   forKey: NSPersistentHistoryTrackingKey)
        
        container.loadPersistentStores { (storeDescription, error) in
            if let error = error {
                // Handle error appropriately in production
                fatalError("Failed to load store: \(error)")
            }
        }
        
        return container
    }()
}