Зашифровать/расшифровать файл .plist ios

У меня есть plist с некоторыми сохраненными данными, и я хочу зашифровать расшифровку, чтобы его нельзя было прочитать, используя цель c. я читал о шифровании AES и т. д., но я хочу, чтобы весь plist был зашифрован каким-то образом, а не строки в plist....

любая помощь будет действительно оценена.


person fizampou    schedule 12.12.2012    source источник
comment
я пробовал это blog.objectgraph.com/index.php/2010/04/20/ и создание бинарного файла   -  person fizampou    schedule 12.12.2012


Ответы (3)


Ссылка, предоставленная 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;

Сам код по-прежнему добавляет пробелы позади, но если он вам нужен для шифрования списка свойств, все будет в порядке.

person frin    schedule 08.05.2013
comment
ссылка предоставлена ​​не мной, ее предоставил пользователь 14356 (оператор) в комментарии к вопросу. - person howanghk; 17.05.2013

Используя код по адресу 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, который вы хотите зашифровать
пароль — это ключ шифрования, который вы хотели бы использовать
encryptedPath< /em> — это место, где вы хотите сохранить зашифрованный файл

расшифровать:

NSData *encryptedData = [NSData dataWithContentsOfFile:encryptedPath];
NSData *plistFileData = [plistFileData AESDecryptWithPassphrase:password];
[plistFileData writeToFile:plistPath atomically:YES];

encryptedPath — это NSString, содержащая путь к зашифрованному файлу plist
пароль — это ключ шифрования, который вы хотите использовать
plistPath здесь вы хотите сохранить расшифрованный файл plist

person howanghk    schedule 12.12.2012
comment
к вашему сведению, пароль можно получить, если он хранится в приложении (например, в виде строки) - person drct; 08.05.2013
comment
правда, однако этого должно быть достаточно, чтобы обычные пользователи не могли читать/изменять файл plist. - person howanghk; 08.05.2013

Вот очень простой ответ на этот вопрос, надеюсь, это упростит проблему, если таковая имеется;

Прежде всего вам необходимо скачать файлы NSData+AES для здесь . Вам просто нужны файлы NSData+AES.h и NSData+AES.m вместе с файлами cipher.h и cipher.m. Оказавшись под стражей, добавьте файлы в свой проект Xcode и удалите заголовок #import Cocoa/Cocoa.h> из NSData+AES.h и cipher.h (только для тех, кто собирается программировать для iOS, если для MacOS, пожалуйста, оставьте заголовок быть). Импортируйте NSData+AES.h в свой файл, где вы извлекаете и записываете свой файл plist.

Теперь, когда заложены начальные основы, мы приступаем к использованию этих важных файлов. Что вам нужно понять, так это то, как вы хотите расшифровывать и шифровать свои данные. При первом запуске вам нужно скопировать ваш 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_ мы должны принудительно сохранить его в AppDelegate.m в didFinishLaunching:

    DataHandler *dataHandler = [[DataHandler alloc] init];
    [dataHandler persistData];

Данные всегда будут зашифрованы в любое время, но в методе copyPlist вы будете заполнять свои модели относительно dataDictionary_ и взаимодействовать с этими моделями. Когда вы закончите, вы сохраните свои модели и снова зашифруете, поэтому ошибок не возникнет. Это простое и довольно работоспособное решение без каких-либо хлопот. Ваше здоровье.

person Mohsin Khubaib Ahmed    schedule 30.08.2014
comment
Вы забыли объяснить, что разработчики iOS должны добавлять #import ‹Foundation/Foundation.h›, когда они удаляют заголовок #import Cocoa/Cocoa.h› - person Aitul; 09.02.2015