Emb*_*der 6 encryption core-data xcode7 swift2
我正在使用Xcode 7.3 for iOS 9.3来尝试加密Core Data文件.我正在尝试使用NSPersistentStoreFileProtectionKey并将其设置为NSFileProtectionComplete以启用加密.它由于某种原因无法工作,我总能看到应用程序生成的.sqlite文件,并浏览sqlitebrowser或iexplorer中的内容.这是我的代码:
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
}()
Run Code Online (Sandbox Code Playgroud)
我还在"功能"中为我的目标启用了数据保护.我已从Apple Developer门户重新生成配置文件,并将其与Enabled Data Protection一起使用.
我还使用以下代码来检查.sqlite,.sqlite-wal和.sqlite-shm文件的文件属性.正确为所有3个NSFileProtectionKey设置了它.
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)
}
}
Run Code Online (Sandbox Code Playgroud)
我还尝试禁用日记模式以防止创建-wal和-shm文件.但我仍然可以阅读.sqlite文件.即使属性读取NSFileProtectionComplete.
如Apple Docs的Apple文档 "使用磁盘加密保护数据"中所述,我试图检查变量protectedDataAvailable的值是否发生变化,如下面的代码所示
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))
}
Run Code Online (Sandbox Code Playgroud)
如果我在没有延迟的情况下检查该值,则将其设置为true,但在添加延迟后将其设置为false.然而,这是一种令人鼓舞的事情,当我下载容器以显示内容时,它仍然具有.sqlite文件,在sqlitebrowser中打开时仍显示内容.
好的,我终于理解了这一点.
使用Xcode 7.3.1 ..
启用文件保护
例:
var options: [NSObject : AnyObject] = [NSMigratePersistentStoresAutomaticallyOption: true,
NSPersistentStoreFileProtectionKey: NSFileProtectionComplete,
NSInferMappingModelAutomaticallyOption: true]
do {
try coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options)
Run Code Online (Sandbox Code Playgroud)
测试文件保护
我无法使用连接到计算机的非越狱设备对此进行测试. 每次以这种方式访问设备的尝试都要求我"信任"计算机,我相信可信任的计算机始终能够读取手机的数据("可信计算机可以与您的iOS设备同步,创建备份,以及访问设备的照片,视频,联系人和其他内容" - https://support.apple.com/en-us/HT202778).我认为SO引用此技术的其他答案对于更新版本的iOS不再有效.实际上,我总是能够使用XCode下载容器并使用iPhone Explorer查看应用程序的数据.那么如何测试......
1 -通过从命令行在.app文件上运行以下命令,创建存档并确保其具有正确的权利:
codesign -d --entitlements :- <path_to_app_binary>
Run Code Online (Sandbox Code Playgroud)
您应该看到代表您的数据保护级别的键/值对.在这个例子中,NSFileProtectionComplete:
<key>com.apple.developer.default-data-protection</key>
<string>NSFileProtectionComplete</string>
Run Code Online (Sandbox Code Playgroud)
另外,我使用以下两种技术来确保数据保护确实有效.它们都需要更改代码.
2 - 添加一些代码以验证是否在文件和/或核心数据存储上设置了正确的NSFileProtectionKey:
NSFileManager.defaultManager().attributesOfItemAtPath(dbPath.path!)
Run Code Online (Sandbox Code Playgroud)
如果我在我的一个文件上打印出来,我会得到:
["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]
Run Code Online (Sandbox Code Playgroud)
注意"NSFileProtectionKey":NSFileProtectionComplete对.
3 - 修改以下代码并将其连接到应用程序中的某个按钮.
@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
}
Run Code Online (Sandbox Code Playgroud)
当您点击按钮时,此代码每隔0.5秒开始执行checkFiles方法.这应该在应用程序的前台或后台无限期运行 - 直到您锁定手机.此时它应该在大约10秒后可靠地失败 - 完全如NSFileProtectionComplete的描述中所述.
我没有在本地级别加密文件,而是为整个应用程序设置 NSFileProtectionComplete。
使用以下内容在应用程序根文件夹中创建文件“entitlements.plist”。
<?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>
Run Code Online (Sandbox Code Playgroud)
然后,如果您还没有这样做(这可能是文件级加密的问题),请在应用程序功能中启用数据保护。
归档时间: |
|
查看次数: |
5076 次 |
最近记录: |