加密/解密 .plist 文件 ios
Posted
技术标签:
【中文标题】加密/解密 .plist 文件 ios【英文标题】:Encrypt/decrypt .plist file ios 【发布时间】:2012-12-12 15:51:29 【问题描述】:我有一个包含一些存储数据的 plist,并且想要加密解密,因此使用目标 c 无法读取它。我已经阅读了有关 AES 加密等的信息,但我希望对整个 plist 进行加密,而不是 plist 中的字符串......
任何帮助将不胜感激。
【问题讨论】:
我已经尝试过blog.objectgraph.com/index.php/2010/04/20/… 并将文件制作成二进制 【参考方案1】:使用https://web.archive.org/web/20150612123348/http://blog.objectgraph.com/index.php/2010/04/20/encrypting-decrypting-base64-encode-decode-in-iphone-objective-c/ 的代码(您在评论中提供的链接),您可以通过以下方式加密您的 plist:
NSData *plistFileData = [NSData dataWithContentsOfFile:plistPath];
NSData *encryptedData = [plistFileData AESEncryptWithPassphrase:password];
[encryptedData writeToFile:encryptedPath atomically:YES];
plistPath 是一个 NSString,其中包含您要加密的 plist 文件的路径password 是您要使用的加密密钥encryptedPath 是您要保存加密文件的位置
解密:
NSData *encryptedData = [NSData dataWithContentsOfFile:encryptedPath];
NSData *plistFileData = [plistFileData AESDecryptWithPassphrase:password];
[plistFileData writeToFile:plistPath atomically:YES];
encryptedPath 是一个包含加密 plist 文件路径的 NSStringpassword 是您要使用的加密密钥plistPath 是您要保存解密后的 plist 文件的位置
【讨论】:
fyi,如果密码存储在应用程序中(例如,作为字符串),则可以检索密码 true,但这应该足以阻止普通用户读取/修改 plist 文件。【参考方案2】:howanghk 提供的链接包含有错误的代码。在该网页上应用 InoriXu 提供的修复程序来解决问题。您必须同时修改加密和解密函数。
所以在一行之后:
const char *password = [pass UTF8String];
添加:
const int passwordLen = [pass length];
换行:
key[i] = password != 0 ? *password++ : 0;
进入:
key[i] = i < passwordLen != 0 ? *password++ : 0;
代码本身仍然在后面添加了一些空格填充,但是如果您需要它来加密属性列表,那就没问题了。
【讨论】:
链接不是我提供的,它是由问题评论中的 user14356(操作员)提供的。【参考方案3】:这是一个非常简单的答案,希望这能简化问题,如果有的话;
首先你需要下载here的NSData+AES文件。您只需要 NSData+AES.h 和 NSData+AES.m 以及 cipher.h 和 cipher.m 文件。一旦被拘留,将文件添加到您的 Xcode 项目并从 NSData+AES.h 和 cipher.h 中删除 #import Cocoa/Cocoa.h> 标头(仅适用于那些打算为 ios 编程的人,如果为 MacOS 请让标头是)。在您获取和写入 plist 文件的文件中导入 NSData+AES.h。
既然已经奠定了最初的基础,我们就开始使用这些重要文件。您需要了解的是您要解密和加密数据的方式。在第一次运行时,您需要将您的 plist 复制到文档文件夹,然后对其进行加密。请注意,如果您复制它并尝试直接解密它会抛出异常,因此为了满足这种情况,我们将使用 UserDefaults 布尔值并在第一次运行时跳过解密。您还需要定义一个预处理器指令常量字符串来处理加密和解密的密钥。这是您的 DataHandler 类中的内容;
#import <Foundation/Foundation.h>
#import "NSData+AES.h"
#define MY_SECRET_KEY @"MY_SECRET_KEY"
static NSMutableDictionary *dataDictionary_ = nil;
static NSMutableDictionary *allSettings_ = nil;
@implementation DataHandler
- (id)init
if(self = [super init])
[self copyPlistData];
return self;
// Encrypt File
- (NSData*)encryptFile:(NSMutableDictionary *)plistDict
NSError *err = nil;
NSData *data = [NSPropertyListSerialization dataWithPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 options:0 error:&err];
NSData *file = [data encryptWithString:MY_SECRET_KEY];
return file;
// Decrypt File
- (NSMutableDictionary *)decryptFile:(NSData *)data
NSError *err = nil;
NSData* newData = [data decryptWithString:MY_SECRET_KEY];
NSPropertyListFormat format;
NSMutableDictionary *file = [NSPropertyListSerialization propertyListWithData:newData options:NSPropertyListMutableContainersAndLeaves format:&format error:&err];
return file;
- (void) copyPlistData
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent: @"myData.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL fileExists = [fileManager fileExistsAtPath:path];
//check if the file exists already in users documents folder
//if file does not exist copy it from the APPLICATION bundle Plist file
if (!fileExists)
NSLog(@"copying database to users documents");
NSString *pathToSettingsInBundle = [[NSBundle mainBundle] pathForResource:@"mydata" ofType:@"plist"];
BOOL copySuccess = [fileManager copyItemAtPath:pathToSettingsInBundle toPath:path error:&error];
if(copySuccess)
noCopyError_ = YES;
//if file is already there do nothing
else
noCopyError_ = YES;
NSLog(@"users database already configured");
BOOL firstRun = [[NSUserDefaults standardUserDefaults] boolForKey:@"IS_FIRST_RUN"];
if(noCopyError_ && firstRun)
dataDictionary_ = [self decryptFile:[NSData dataWithContentsOfFile:path]];
else
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"IS_FIRST_RUN"];
[[NSUserDefaults standardUserDefaults] synchronize];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:@"mydata.plist"];
dataDictionary_ = (NSMutableDictionary*)[[NSDictionary alloc ] initWithContentsOfFile:plistPath];
NSMutableDictionary *data = (NSMutableDictionary*)[dictionaryDATA_ objectForKey:@"Data"];
allSettings_ = [data objectForKey:@"AllSettings"];
- (NSMutableDictionary*) properties
NSMutableDictionary * props = [[NSMutableDictionary alloc]init];
[props setObject: allSettings_ forKey:@"AllSettings"];
NSMutableDictionary * data = [NSMutableDictionary dictionaryWithObject:props forKey:@"Data"];
return data;
- (void)persistData
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *plistPath = [documentsDirectory stringByAppendingPathComponent:@"mydata.plist"];
NSMutableDictionary *dict = [self properties];
NSData *encryptedDict = [self encryptFile:dict];
[encryptedDict writeToFile:plistPath atomically:YES];
但是第一次填充 dataDictionary_ 时,我们必须在 didFinishLaunching 的 AppDelegate.m 中强行将其持久化:
DataHandler *dataHandler = [[DataHandler alloc] init];
[dataHandler persistData];
数据将始终被加密,但在 copyPlist 方法中,您将根据 dataDictionary_ 填充模型并与这些模型进行交互。完成后,您将保留模型并再次加密,因此不会发生错误。这是一个简单且非常可行的解决方案,没有任何麻烦。干杯。
【讨论】:
你忘了说明IOS开发者在移除#import Cocoa/Cocoa.h> header时需要添加#import以上是关于加密/解密 .plist 文件 ios的主要内容,如果未能解决你的问题,请参考以下文章