---
title: Bật Data Protection (NSFileProtectionComplete) cho file chứa dữ liệu nhạy cảm
impact: HIGH
impactDescription: File không có Data Protection class có thể bị đọc ngay cả khi device bị khóa (accessible after first unlock). Với NSFileProtectionComplete, file chỉ accessible khi device đang mở khóa, được mã hóa bằng user passcode.
tags: swift, ios, data-protection, file-encryption, nsdatawritingoptions, secure-storage, security
---

## Bật Data Protection (NSFileProtectionComplete) cho file chứa dữ liệu nhạy cảm

iOS Data Protection mã hóa file bằng key kết hợp từ passcode device và hardware key. Khi tạo hoặc ghi file nhạy cảm, phải set attribute `NSFileProtectionComplete` (mạnh nhất - chỉ decrypt khi device đang unlock). Database CoreData và SQLite cũng cần bật encryption.

**Incorrect (không set data protection):**

```swift
import Foundation

class DocumentManager {
    // !! Ghi file không có data protection - accessible mọi lúc
    func savePrivateDocument(content: Data, filename: String) throws {
        let url = documentsDirectory.appendingPathComponent(filename)
        // Không set protection attribute - mặc định là NSFileProtectionCompleteUntilFirstUserAuthentication
        try content.write(to: url)
    }

    // !! SQLite database không có data protection
    func openDatabase() -> OpaquePointer? {
        let dbPath = documentsDirectory.appendingPathComponent("app.db").path
        var db: OpaquePointer?
        sqlite3_open(dbPath, &db)  // Không có encryption!
        return db
    }
}
```

**Correct (NSFileProtectionComplete + FMDB encryption):**

```swift
import Foundation

class SecureDocumentManager {
    private let documentsDirectory = FileManager.default
        .urls(for: .documentDirectory, in: .userDomainMask)[0]

    // SAFE: Data Protection Complete cho file nhạy cảm
    func savePrivateDocument(content: Data, filename: String) throws {
        let url = documentsDirectory.appendingPathComponent(filename)
        // NSFileProtectionComplete: chỉ accessible khi device unlocked
        try content.write(
            to: url,
            options: [.atomic, .completeFileProtection]  // .completeFileProtection = NSFileProtectionComplete
        )
    }

    // SAFE: Set protection cho file đã tồn tại
    func upgradeFileProtection(at url: URL) throws {
        try FileManager.default.setAttributes(
            [.protectionKey: FileProtectionType.complete],
            ofItemAtPath: url.path
        )
    }

    // SAFE: Kiểm tra data protection của file
    func verifyFileProtection(at url: URL) throws -> Bool {
        let attributes = try FileManager.default.attributesOfItem(atPath: url.path)
        let protection = attributes[.protectionKey] as? FileProtectionType
        return protection == .complete || protection == .completeUnlessOpen
    }

    // SAFE: Tạo directory với data protection
    func createSecureDirectory(named name: String) throws -> URL {
        let dirURL = documentsDirectory.appendingPathComponent(name)
        try FileManager.default.createDirectory(
            at: dirURL,
            withIntermediateDirectories: true,
            attributes: [.protectionKey: FileProtectionType.complete]
        )
        return dirURL
    }
}

// SAFE: CoreData với data protection (trong NSPersistentStoreDescription)
class CoreDataStack {
    lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "AppModel")
        let description = NSPersistentStoreDescription()
        description.url = FileManager.default
            .urls(for: .documentDirectory, in: .userDomainMask)[0]
            .appendingPathComponent("AppModel.sqlite")
        // SAFE: Enable SQLite data protection
        description.setOption(
            FileProtectionType.complete as NSObject,
            forKey: NSPersistentStoreFileProtectionKey
        )
        container.persistentStoreDescriptions = [description]
        container.loadPersistentStores { _, error in
            if let error = error { fatalError("CoreData load error: \(error)") }
        }
        return container
    }()
}

// SAFE: App entitlement - trong Xcode → Signing & Capabilities → Data Protection
// Chọn "Complete Protection" trong Data Protection capability
```

**Tools:** OWASP MASVS-STORAGE-4, iMazing (verify protection class), `filecmds` on jailbroken device, Xcode Capabilities (Data Protection entitlement)
