2012-12-12 19 views
7

Ho un plist con alcuni dati memorizzati e voglio cifrare decrypt in modo che non sia leggibile usando l'obiettivo c. ho letto sulla crittografia AES, ecc, ma voglio che l'intero plist sia crittografato come non le stringhe nel plist ....Encrypt/decrypt .plist file ios

qualsiasi aiuto sarà davvero apprezzato.

+0

ho provato questo http://blog.objectgraph.com/index.php/2010/04/20/encrypting-decrypting-base64-encode-decode-in-iphone-objective-c/ e rendendo il file binario – zaabalonso

risposta

2

Il collegamento fornito da howanghk contiene co de con un bug. Applicare la correzione fornita da InoriXu in quella pagina Web per risolvere il problema. È necessario modificare entrambe le funzioni di crittografia e decrittografia.

Così, dopo una linea:

const char *password = [pass UTF8String]; 

aggiuntivo:

const int passwordLen = [pass length]; 

E il cambiamento linea:

key[i] = password != 0 ? *password++ : 0; 

in:

key[i] = i < passwordLen != 0 ? *password++ : 0; 

Il codice stesso aggiunge ancora un po 'di spazio vuoto dietro, ma se ne hai bisogno per crittografare un elenco di proprietà, starai bene.

+0

il link non è stato fornito da me, è stato fornito dall'utente 14356 (op) nel commento della domanda. – howanghk

4

Utilizzando il codice a http://blog.objectgraph.com/index.php/2010/04/20/encrypting-decrypting-base64-encode-decode-in-iphone-objective-c/ (il link che hai fornito nel commento), è possibile crittografare i plist da:

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

plistPath è un NSString che contiene il percorso del file plist che si desidera crittografare
la password è la chiave di crittografia che si desidera utilizzare
encryptedPath è dove si desidera salvare il file crittografato

a decifrare:

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

encryptedPath è un NSString che contiene il percorso del file plist crittografato
la password è la chiave di crittografia che si desidera utilizzare
plistPath è dove si desidera salvare il file plist decodificato

+0

questo è quello che ho fatto ma il plist non è leggibile dopo la decrittazione .... – zaabalonso

+0

fyi, è possibile recuperare la password se è memorizzata all'interno dell'app (es. Come una stringa per esempio) – drct

+1

true, tuttavia questo dovrebbe essere sufficiente per fermarsi utenti occasionali leggendo/modificando il file plist. – howanghk

3

Ecco una risposta molto semplice a questo, spero che questo semplifica il problema, se del caso;

Per prima cosa è necessario scaricare i file NSData + AES per here. È necessario solo NSData + AES.h & NSData + AES.m insieme ai file cipher.h & cipher.m. Una volta in custodia, aggiungi i file al tuo progetto Xcode e rimuovi #import Cocoa/Cocoa.h> header da NSData + AES.h e cipher.h (solo per coloro che intendono programmare per iOS, se per MacOS si prega di lasciare l'intestazione essere). Importa NSData + AES.h nel tuo file in cui recuperi e scrivi il tuo file plist.

Ora che le basi iniziali sono state stabilite, ci assumiamo l'uso di questi file importanti. Quello che devi capire è il modo in cui vuoi decodificare e crittografare i tuoi dati.Alla prima esecuzione è necessario copiare il plist nella cartella documenti e quindi crittografarlo. Nota, se lo copi e provi a decifrarlo, verrà generata un'eccezione e, per ovviare a questo, utilizzeremo un valore booleano UserDefaults e salterai la decrittografia alla prima esecuzione. Inoltre, è necessario definire una stringa costante di direttiva preprocessore per intrattenere la chiave segreta per la crittografia e la decrittografia. Ecco cosa avrai nella classe 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]; 
    } 

Ma la prima volta il dataDictionary_ è popolato, dobbiamo per forza abilmente persistere in AppDelegate.m in didFinishLaunching:

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

I dati saranno sempre criptati in ogni momento, ma nel copyPlist metodo popolerai i tuoi modelli rispetto a dataDictionary_ e interagirai con quei modelli. Al termine, i tuoi modelli verranno mantenuti e criptati nuovamente, quindi non si verificheranno errori. È semplice e una soluzione abbastanza praticabile senza problemi. Saluti.

+0

Si dimentica di spiegare che gli sviluppatori IOS devono aggiungere #import quando rimuovono #import Cocoa/Cocoa.h> header – Aitul