2016-08-25 3 views
6

Ich bin mit Xcode 7.3 für iOS 9.3, um zu versuchen und eine Core Data-Datei zu verschlüsseln. Ich versuche, NSPersistentStoreFileProtectionKey zu verwenden und auf NSFileProtectionComplete festzulegen, um die Verschlüsselung zu aktivieren. Es ist aus irgendeinem Grund nicht funktioniert und ich kann immer die .sqlite Datei von der App und klicken Sie sich durch den Inhalt in sqlitebrowser oder iexplorer erzeugt sehen. Hier ist mein Code:NSFileProtectionComplete nicht verschlüsselt die Kerndatendatei

lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = { 
    // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail. 

    // Create the coordinator and store 
    let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel) 
    let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite") 
    var failureReason = "There was an error creating or loading the application's saved data." 


    let dict: [NSObject : AnyObject] = [ 
     NSPersistentStoreFileProtectionKey  : NSFileProtectionComplete 
    ] 

    do { 
     try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: dict) 
    } catch { 
     // Report any error we got. 
     var dict = [String: AnyObject]() 
     dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data" 
     dict[NSLocalizedFailureReasonErrorKey] = failureReason 

     dict[NSUnderlyingErrorKey] = error as NSError 
     let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict) 
     // Replace this with code to handle the error appropriately. 
     // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
     NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)") 
     abort() 
    } 

    do { 
     let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite") 
     try NSFileManager.defaultManager().setAttributes([NSFileProtectionKey : NSFileProtectionComplete], ofItemAtPath: url.path!) 

    } catch { 

    } 

    do { 
     let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite-wal") 
     try NSFileManager.defaultManager().setAttributes([NSFileProtectionKey : NSFileProtectionComplete], ofItemAtPath: url.path!) 
     //   try print(NSFileManager.defaultManager().attributesOfFileSystemForPath(String(url))) 

    } catch { 

    } 

    do { 
     let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite-shm") 
     try NSFileManager.defaultManager().setAttributes([NSFileProtectionKey : NSFileProtectionComplete], ofItemAtPath: url.path!) 
     //   try print(NSFileManager.defaultManager().attributesOfFileSystemForPath(String(url))) 

    } catch { 

    } 


    return coordinator 
}() 

Ich habe auch Data Protection für mein Ziel in den "Fähigkeiten" aktiviert. Ich habe das Provisioning-Profil vom Apple Developer Portal neu erstellt und verwende dieses mit Enabled Data Protection.

Ich bin auch mit dem folgenden Code die Dateiattribute von .sqlite, .sqlite-wal und .sqlite-shm-Dateien zu überprüfen. NSFileProtectionKey ist für alle 3 korrekt eingestellt.

func checkProtectionForLocalDb(atDir : String){ 

    let fileManager = NSFileManager.defaultManager() 
    let enumerator: NSDirectoryEnumerator = fileManager.enumeratorAtPath(atDir)! 


    for path in enumerator { 

     let attr : NSDictionary = enumerator.fileAttributes! 
     print(attr) 


    } 


} 

Ich habe auch versucht die Journal-Modus zu deaktivieren -wal und -shm Dateien zu verhindern, erstellt werden. Aber ich kann immer noch die .sqlite Datei lesen. Obwohl die Attribute NSFileProtectionComplete lesen.

Wie bei Apple Docs in der Apple-Dokumentation unter „On Disk Encryption mit Daten zu schützen“, versuchte ich, ob der Wert der Variablen protectedDataAvailable Änderungen zu überprüfen, wie unter

public func applicationDidEnterBackground(application: UIApplication) { 
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 
    NSThread.sleepForTimeInterval(10) 
    sleep(10) 
    let dataAvailable : Bool = UIApplication.sharedApplication().protectedDataAvailable 
    print("Protected Data Available : " + String(dataAvailable)) 

} 

im Code angezeigt Wenn ich das überprüfen Wert ohne die Verzögerung ist es auf True gesetzt, aber nach dem Hinzufügen der Verzögerung ist es auf false gesetzt. Dies ist eine Art ermutigend, aber gleich nach, wenn ich die Container herunterzuladen, um den Inhalt zu zeigen, ist es noch .sqlite Datei hat, das immer noch den Inhalt zeigt, wenn in sqlitebrowser geöffnet.

+0

Wie testen Sie? Wie ist der Status der App (offen/geschlossen/erledigt) und des Geräts (offen/gesperrt) beim Testen? – Wain

+0

Ich habe die App im Öffnen/Schließen und Gerät gesperrt/entsperrt Zustände getestet. Ein Szenario, bei dem ich hoffte, dass es immer funktionieren würde, war, als das Gerät gesperrt war, aber mit Xcode verbunden war und ich den Container mit einem neuen Zeitstempel und einer neuen Versionsnummer heruntergeladen hatte, aber die Daten trotzdem lesen konnte. – EmbCoder

Antwort

0

Anstatt eine Datei auf der lokalen Ebene verschlüsseln ich NSFileProtectionComplete für die App als Ganzes gesetzt.

Erstellen Sie die Datei ‚entitlements.plist‘ in Ihren Anwendungen Stammordner mit folgendem Inhalt.

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> 
<plist version="1.0"> 
<dict> 
    <key>DataProtectionClass</key> 
    <string>NSFileProtectionComplete</string> 
</dict> 
</plist> 

Dann, wenn Sie nicht bereits getan hat bereits (dies könnte das Problem mit der Dateiebene Verschlüsselung sein) ermöglicht Data Protection in Ihren Apps-Funktionen.

enter image description here

+0

Wie in meiner Frage angegeben, habe ich bereits versucht, Data Protection innerhalb von Xcode unter "Capability" als Screenshot zu aktivieren, aber es hat nicht funktioniert. Ich habe Data Protection auch im Entwicklungsprovisionierungsprofil aktiviert und neu generiert und installiert. Nichts davon hat funktioniert. Was den Code angeht, den Sie oben für "entity.plist" eingefügt haben, ist es das Gleiche wie beim Einfügen in die Info.Plist oder soll ich die neue Datei erstellen? Was ist Ihre empfohlene Methode zum Testen der aktivierten Verschlüsselung? Ich bin immer in der Lage, die .sqlite-Datei zu öffnen, selbst nachdem das Gerät gesperrt wurde. – EmbCoder

+0

@EmbCoder Testen: Ich habe meine vorherige Antwort aktualisiert, um zu überprüfen, dass Ihr Sicherheitscode sofort eingestellt ist und die Wartezeit einschließt, um das Gerät zu verschlüsseln (Ich habe dies Dutzende Male versucht, bevor die Verschlüsselung eine 10- 20 Sekunden Verzögerung). http://StackOverflow.com/a/36597020/957245 – Deco

+0

@EmbCoder Die Berechtigung plist ist eine andere Entität als Ihre info.plist. Den DataProtection Schlüssel in info.plist zu setzen, funktionierte nicht für mich. – Deco

6

Ok, ich das endlich verstehen.

Xcode 7.3.1 ..

Aktivieren der Dateischutz

  1. Dateischutz Aktivieren Sie die Registerkarte Funktionen auf Ihrem App Ziel mit
  2. Wenn Sie die Standard NSFileProtectionComplete nicht wollen, ändern Diese Einstellung im Entwicklerportal unter Ihrer App-ID
  3. Stellen Sie sicher, dass XCode über das neue Bereitstellungsprofil verfügt, das erstellt wird.
  4. Zum Schutz von Dateien erstellt Ihre App, das ist es.
  5. Um Core Data zu schützen, müssen Sie die Option NSPersistentStoreFileProtectionKey: NSFileProtectionComplete zu Ihrem persistenten Speicher hinzufügen.

Beispiel:

var options: [NSObject : AnyObject] = [NSMigratePersistentStoresAutomaticallyOption: true, 
        NSPersistentStoreFileProtectionKey: NSFileProtectionComplete, 
       NSInferMappingModelAutomaticallyOption: true] 
    do { 
     try coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options) 

Testing Dateischut

Ich bin nicht in der Lage, dies zu testen, ein nicht-jailbroken Gerät an einen Computer angeschlossen. Jeder Versuch, auf diese Weise auf das Gerät zuzugreifen, erfordert, dass ich dem Computer vertraue und glaube, dass vertrauenswürdige Computer die Daten des Telefons immer lesen können ("Vertrauenswürdige Computer können mit Ihrem iOS-Gerät synchronisieren, Backups erstellen und auf die Fotos Ihres Geräts zugreifen , Videos, Kontakte und andere Inhalte "- https://support.apple.com/en-us/HT202778). Ich denke, die anderen Antworten zu SO, die diese Technik referenzieren, sind mit neueren Versionen von iOS nicht mehr gültig. In der Tat bin ich immer in der Lage, den Container mit XCode herunterladen und die Daten der App mit iPhone Explorer anzeigen. So, wie Sie testen ...

1 - ein Archiv erstellen und sicherstellen, dass es hat die richtigen Berechtigungen durch die folgende auf der .app-Datei von der Kommandozeile ausgeführt wird:

codesign -d --entitlements :- <path_to_app_binary> 

Sie sollten Sehen Sie sich ein Schlüssel/Wert-Paar an, das Ihre Datenschutzstufe darstellt. In diesem Beispiel NSFileProtectionComplete:

<key>com.apple.developer.default-data-protection</key> 
<string>NSFileProtectionComplete</string> 

Darüber hinaus habe ich die folgenden beiden Techniken selbst zu überzeugen, dass der Datenschutz in der Tat funktioniert. Beide erfordern Codeänderungen.

2 - einige Codes hinzufügen, um zu überprüfen, dass die richtige NSFileProtectionKey auf Ihren Dateien festgelegt wird und/oder Kerndatenspeicher:

NSFileManager.defaultManager().attributesOfItemAtPath(dbPath.path!) 

Wenn ich das Ausdrucken auf einem meiner Dateien erhalte ich:

["NSFileCreationDate": 2016-10-14 02:06:39 +0000, "NSFileGroupOwnerAccountName": mobile, "NSFileType": NSFileTypeRegular, "NSFileSystemNumber": 16777218, "NSFileOwnerAccountName": mobile, "NSFileReferenceCount": 1, "NSFileModificationDate": 2016-10-14 02:06:39 +0000, "NSFileExtensionHidden": 0, "NSFileSize": 81920, "NSFileGroupOwnerAccountID": 501, "NSFileOwnerAccountID": 501, "NSFilePosixPermissions": 420, "NSFileProtectionKey": NSFileProtectionComplete, "NSFileSystemFileNumber": 270902] 

Beachten Sie die "NSFileProtectionKey": NSFileProtectionComplete Paar.

3 - Ändern Sie den folgenden Code und schließen Sie ihn an eine Schaltfläche in Ihrer App an.

@IBAction func settingButtonTouch(sender: AnyObject) { 
     updateTimer = NSTimer.scheduledTimerWithTimeInterval(0.5, target: self, 
                  selector: #selector(TabbedOverviewViewController.runTest), userInfo: nil, repeats: true) 
     registerBackgroundTask() 
} 

var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid 
var updateTimer: NSTimer? 

func registerBackgroundTask() { 
    backgroundTask = UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler { 
     [unowned self] in 
     self.endBackgroundTask() 
    } 
    assert(backgroundTask != UIBackgroundTaskInvalid) 
} 

func endBackgroundTask() { 
    NSLog("Background task ended.") 
    UIApplication.sharedApplication().endBackgroundTask(backgroundTask) 
    backgroundTask = UIBackgroundTaskInvalid 
} 

func runTest() { 
    switch UIApplication.sharedApplication().applicationState { 
    case .Active: 
     NSLog("App is active.") 
     checkFiles() 
    case .Background: 
     NSLog("App is backgrounded.") 
     checkFiles() 
    case .Inactive: 
     break 
    } 
} 

func checkFiles() { 
    //attempt to access a protected resource, i.e. a core data store or file 
} 

Wenn Sie die Taste dieser Code beginnt tippen Sie auf die checkFiles Methode alle 0,5 Sekunden ausgeführt werden. Dies sollte auf unbegrenzte Zeit mit der App im Vordergrund oder Hintergrund laufen - bis Sie Ihr Telefon sperren. An diesem Punkt sollte es nach ca. 10 Sekunden zuverlässig ausfallen - genau wie in der Beschreibung von NSFileProtectionComplete beschrieben.

+0

Es funktioniert nicht, nachdem der Timer der Sperrvorrichtung gestoppt wurde. –

Verwandte Themen