Как защитить файлы пакета iOS, такие как plist, image, sqlite, media files

Я создал образец проекта hello world, а затем добавил файл Data.plist в папку ресурсов. Теперь люди могут легко получить файлы пакета, распакуя файл .ipa. Есть ли способ защитить файл Data.plist, который сохраняется в комплекте приложений iPhone?

 Encryption is a decent method of scrambling the data but i don't know how to implement encription concept.

Есть ли у вас образец кода?

enter image description here

    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"Data" ofType:@"plist"];
    NSArray *arrData = [[NSArray alloc]initWithContentsOfFile:filePath];

    NSData *datas = [NSKeyedArchiver archivedDataWithRootObject:arrData];
    [datas writeToFile:filePath atomically:YES];

После извлечения файла IPA

enter image description here

Ответ 1

  • зашифровать файлы на Mac... во время развертывания:

    FIRST: не добавляйте файлы для шифрования в целевой
    например Encryption-Test.plist

    Затем добавьте фазу оболочки script к вашему проекту xcode, чтобы использовать openssl для шифрования и копирования файлов.
    например,
    openssl enc -e -aes-256-cbc -pass pass:asdasd -in $PROJECT_DIR/test/Encryption-Test.plist -out $TARGET_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/Encryption-Test.enc

  • добавить исходные файлы RNCryptor из github в ваш проект. Это делает дешифровку openSSL зашифрованных файлов AES очень просто. (Спасибо rob!) https://github.com/RNCryptor/RNCryptor (Apple CCrypt api не очень удобно работать напрямую)

  • загружать данные и расшифровывать их:

например.

@implementation TestViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSString *path = [[NSBundle mainBundle] pathForResource:@"Encryption-Test" ofType:@"enc"];
    NSData *passEncryptedData =[[NSData alloc] initWithContentsOfFile:path];
    NSString *pass = @"asdasd";

    NSData *dataDecrypted = [RNOpenSSLDecryptor decryptData:passEncryptedData withSettings:kRNCryptorAES256Settings password:pass error:nil];
    id plist = [NSPropertyListSerialization propertyListFromData:dataDecrypted mutabilityOption:NSPropertyListImmutable format:nil errorDescription:nil];

    assert(plist);
    self.text.text = [plist description];
}

@end

добавлен полный образец: https://github.com/Daij-Djan/encryptBundleFiles

Ответ 2

Я успешно справился с приведенными выше примерами и, наконец, нашел код, который позволяет вам расшифровать зашифрованный файл (на самом деле, файл) с помощью openssl. Я работаю в папке с документами для этого пример, и я не использую никаких сценариев оболочки. Вот как это сделать:

  • Зашифруйте свой файл в терминале следующим образом:
openssl aes-256-cbc -in questions.plist -out questions.enc
  1. Добавьте файл в проект Xcode, перетащив их в каталог поддерживающих файлов
  2. Загрузите библиотеку RNCryptor здесь.
  3. Найдите библиотеку RNCryptor в загруженном проекте: encryptBundleFiles-master/test/RNCryptor и добавьте их в проект Xcode.
  4. Импортируйте файлы RNDecryptor.h и RNOpenSSLDecryptor.h в ваш файл класса, например файл ExampleViewController.m.
  5. Добавьте код ниже, из которого вы хотите его вызвать, например, определенную функцию.

  6. И все готово. Теперь вы можете использовать файл plist, чтобы, например, заполнить таблицу.

// Copy the plist file from the resources folder to the documents folder
    NSFileManager *fileManager = [NSFileManager defaultManager];
        NSError *error;
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];

    NSString *txtPath = [documentsDirectory stringByAppendingPathComponent:@"questions.enc"];

    if ([fileManager fileExistsAtPath:txtPath] == NO) {
        NSString *resourcePath = [[NSBundle mainBundle] pathForResource:@"questions" ofType:@"enc"];
        [fileManager copyItemAtPath:resourcePath toPath:txtPath error:&error];
    }

    NSString *filePath1 = [documentsDirectory stringByAppendingPathComponent:@"questions.encr"];

    NSData *passEncryptedData =[[NSData alloc] initWithContentsOfFile:filePath1]  ;
    NSString *pass = @"asdf"; // Insert your password from step 1

    NSData *dataDecrypted = [RNOpenSSLDecryptor decryptData:passEncryptedData withSettings:kRNCryptorAES256Settings password:pass error:&error];

        NSString *appFile = [documentsDirectory stringByAppendingPathComponent:@"questionsDECRYPTED.plist"]; //The Decrypted file saved here
        [dataDecrypted writeToFile:appFile atomically:YES];

Ответ 3

На основе решения Daij-Dan я создал пару расширений Swift String. Требуется RNCryptor

Они используются так:

//Decrypt a UIImage
let decryptedImage = "encyptedFileNameInBundle".decryptedImage(password: "test")

//Decrypt NSData
let decryptedData = "encyptedDataFileNameInBundle".decryptedData(password: "test")

Строка - это имя файла ресурса, который был добавлен в ресурсы пакета. Предполагается, что файл имеет расширение "enc" по умолчанию, в противном случае передайте расширение файла с помощью "fileExtension:".

Расширение:

public extension String {

    func decryptedImage(password: String, fileExtension: String = "enc") -> UIImage? {

         //create encypted file with:
         //openssl aes-256-cbc -in fileName.jpg -out fileName.enc

        if let decryptedData = self.decryptedData(password: password, fileExtension: fileExtension) {
            return UIImage(data: decryptedData)
        }

        return nil
     }

    func decryptedData(password: String, fileExtension: String = "enc") -> Data? {

        //create encypted file with:
        //openssl aes-256-cbc -in fileName.data -out fileName.enc

        if let fileURL = Bundle.main.url(forResource: self, withExtension: fileExtension) {

            do {
                let encyptedData = try Data(contentsOf: fileURL)
                return try RNOpenSSLDecryptor.decryptData(encyptedData, with: kRNCryptorAES256Settings, password: password)
            } catch {
                print("encryptedImage ERR: \(error.localizedDescription)")
            }
        }

        return nil
    }
}

Ответ 4

Используйте NSKeyedArchiver для создания объекта NSData из вашего словаря (NSKeyedArchiver archivedDataWithRootObject:). Затем зашифруйте NSData с помощью AES и напишите это в свой файл.

Чтение только обратного процесса: сначала прочитайте NSData, расшифруйте его с помощью метода из указанной ссылки, затем передайте расшифрованные NSData NSKeyedUnarchiver (NSKeyedUnarchiver unarchiveObjectWithData:), и вы вернете свой словарь. Это можно использовать для файла plist или NSDictionary для обеспечения безопасности ваших данных.

Пример 1:

Пример 2:

ИЗМЕНИТЬ 2:

NSDictionary *Your_NSDictionary = [NSDictionary dictionaryWithObjectsAndKeys:
                           @"Obj1", @"Key1",
                           @"Obj2", @"Key2", nil];
//store dictionary
NSMutableData *yourData = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:Your_NSDictionary forKey: @"key"];
[archiver finishEncoding];
[yourData writeToFile:@"FilePath" atomically:YES];

или

NSString* filePath = [[NSBundle mainBundle] pathForResource:@"Data" 
                                                 ofType:@"plist"];
NSDictionary* data = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSMutableDictionary * rootObject;
rootObject = [NSMutableDictionary dictionary];
[rootObject setValue: data forKey:@"accounts"];
[NSKeyedArchiver archiveRootObject: rootObject toFile: path];