What is the best way to keep records on iPhone to prevent hacking?

I am currently using NSUserDefaults, but I heard that Jailbreakers can easily change these values ​​and spoof Game Center. Should I encrypt the value that I am storing? Should I use a keychain instead? Should I store the value in binary format in NSUserDefualts using BOOL (maybe not)? What is the best way to keep a record to prevent hacking and how is it done?

+6
source share
3 answers

Any data that should be accessible only through code and should be safe fits perfectly into KeyChain.

If this is more than just a little data, then encrypting it and storing it in the document directory can also do the job. But if someone really wanted, they disassembled your application and tried to find the encryption key. Not easy, but can be done.

+3
source

This is the code I use, some of them are taken from the Internet

I understood this idea: https://github.com/matthiasplappert/Secure-NSUserDefaults


how to use

in AppDelegate.m

#import "NSUserDefaults+SecureUserDefaults.h" - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [NSUserDefaults setSecret:@"soem secret string"]; //Cracker can still read the secret string from the binary through // other initialize step } 

when do you want to use

 [[NSUserDefaults standardUserDefaults] arrayForKey:@"key" defaultValue:nil]; // if the content is modified or not exist will return default value that passed in [[NSUserDefaults standardUserDefaults] setSecureObject:object forKey:@"key"]; // check more method in NSUserDefaults+SecureUserDefaults.h 

code here

NSData + Encryption_AES256.h

 #import <Foundation/Foundation.h> @interface NSData (Encryption_AES256) - (NSData *)encryptedDataWithKey:(NSData *)key; - (NSData *)decryptedDataWithKey:(NSData *)key; @end 

NSData + Encryption_AES256.m

 #import "NSData+Encryption_AES256.h" #import <CommonCrypto/CommonCryptor.h> // Key size is 32 bytes for AES256 #define kKeySize kCCKeySizeAES256 @implementation NSData (Encryption_AES256) - (NSData*) makeCryptedVersionWithKeyData:(const void*) keyData ofLength:(int) keyLength decrypt:(bool) decrypt { // Copy the key data, padding with zeroes if needed char key[kKeySize]; bzero(key, sizeof(key)); memcpy(key, keyData, keyLength > kKeySize ? kKeySize : keyLength); size_t bufferSize = [self length] + kCCBlockSizeAES128; void* buffer = malloc(bufferSize); size_t dataUsed; CCCryptorStatus status = CCCrypt(decrypt ? kCCDecrypt : kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, key, kKeySize, NULL, [self bytes], [self length], buffer, bufferSize, &dataUsed); switch(status) { case kCCSuccess: return [NSData dataWithBytesNoCopy:buffer length:dataUsed]; case kCCParamError: NSLog(@"Error: NSDataAES256: Could not %s data: Param error", decrypt ? "decrypt" : "encrypt"); break; case kCCBufferTooSmall: NSLog(@"Error: NSDataAES256: Could not %s data: Buffer too small", decrypt ? "decrypt" : "encrypt"); break; case kCCMemoryFailure: NSLog(@"Error: NSDataAES256: Could not %s data: Memory failure", decrypt ? "decrypt" : "encrypt"); break; case kCCAlignmentError: NSLog(@"Error: NSDataAES256: Could not %s data: Alignment error", decrypt ? "decrypt" : "encrypt"); break; case kCCDecodeError: NSLog(@"Error: NSDataAES256: Could not %s data: Decode error", decrypt ? "decrypt" : "encrypt"); break; case kCCUnimplemented: NSLog(@"Error: NSDataAES256: Could not %s data: Unimplemented", decrypt ? "decrypt" : "encrypt"); break; default: NSLog(@"Error: NSDataAES256: Could not %s data: Unknown error", decrypt ? "decrypt" : "encrypt"); } free(buffer); return nil; } - (NSData* )encryptedDataWithKey:(NSData *)key { return [self makeCryptedVersionWithKeyData:[key bytes] ofLength:[key length] decrypt:NO]; } - (NSData* )decryptedDataWithKey:(NSData *)key { return [self makeCryptedVersionWithKeyData:[key bytes] ofLength:[key length] decrypt:YES]; } @end 

NSUserDefaults + SecureUserDefaults.h

 // // NSUserDefaults+SecureUserDefaults.h // PocketMoneyExchanger // // Created by Xiliang Chen on 12-1-17. // Copyright (c) 2012εΉ΄ Xiliang Chen. All rights reserved. // #import <Foundation/Foundation.h> @interface NSUserDefaults (SecureUserDefaults) + (void)setSecret:(NSString *)secret; - (id)objectForKey:(NSString *)defaultName defaultValue:(id)value; - (void)setSecureObject:(id)value forKey:(NSString *)defaultName; - (NSString *)stringForKey:(NSString *)defaultName defaultValue:(NSString *)value; - (NSArray *)arrayForKey:(NSString *)defaultName defaultValue:(NSArray *)value; - (NSDictionary *)dictionaryForKey:(NSString *)defaultName defaultValue:(NSDictionary *)value; - (NSData *)dataForKey:(NSString *)defaultName defaultValue:(NSData *)value; - (NSArray *)stringArrayForKey:(NSString *)defaultName defaultValue:(NSArray *)value; - (NSInteger)integerForKey:(NSString *)defaultName defaultValue:(NSInteger)value; - (float)floatForKey:(NSString *)defaultName defaultValue:(float)value; - (double)doubleForKey:(NSString *)defaultName defaultValue:(double)value; - (BOOL)boolForKey:(NSString *)defaultName defaultValue:(BOOL)value; - (void)setSecureInteger:(NSInteger)value forKey:(NSString *)defaultName; - (void)setSecureFloat:(float)value forKey:(NSString *)defaultName; - (void)setSecureDouble:(double)value forKey:(NSString *)defaultName; - (void)setSecureBool:(BOOL)value forKey:(NSString *)defaultName; @end 

NSUserDefaults + SecureUserDefaults.m

 // // NSUserDefaults+SecureUserDefaults.m // PocketMoneyExchanger // // Created by Xiliang Chen on 12-1-17. // Copyright (c) 2012εΉ΄ Xiliang Chen. All rights reserved. // #import "NSUserDefaults+SecureUserDefaults.h" #import "NSData+Encryption_AES256.h" static NSData *secretData; @implementation NSUserDefaults (SecureUserDefaults) + (void)setSecret:(NSString *)secret { secretData = [secret dataUsingEncoding:NSUnicodeStringEncoding]; } - (id)objectForKey:(NSString *)defaultName defaultValue:(id)value { id obj = [self objectForKey:defaultName]; if ([obj isKindOfClass:[NSData class]]) { NSData *secureData = obj; NSData *data = [secureData decryptedDataWithKey:secretData]; if (data) { return [NSKeyedUnarchiver unarchiveObjectWithData:data]; } } return value; } - (void)setSecureObject:(id)value forKey:(NSString *)defaultName { if (value == nil || defaultName == nil) { return [self setObject:value forKey:defaultName]; } NSData *tobesaved = [NSKeyedArchiver archivedDataWithRootObject:value]; NSData *secureData = [tobesaved encryptedDataWithKey:secretData]; //NSAssert(secureData != nil, @"fail to encrpty data"); [self setObject:secureData forKey:defaultName]; } - (NSString *)stringForKey:(NSString *)defaultName defaultValue:(NSString *)value { id obj = [self objectForKey:defaultName defaultValue:value]; if ([obj isKindOfClass:[NSString class]]) { return obj; } return value; } - (NSArray *)arrayForKey:(NSString *)defaultName defaultValue:(NSArray *)value { id obj = [self objectForKey:defaultName defaultValue:value]; if ([obj isKindOfClass:[NSArray class]]) { return obj; } return value; } - (NSDictionary *)dictionaryForKey:(NSString *)defaultName defaultValue:(NSDictionary *)value { id obj = [self objectForKey:defaultName defaultValue:value]; if ([obj isKindOfClass:[NSDictionary class]]) { return obj; } return value; } - (NSData *)dataForKey:(NSString *)defaultName defaultValue:(NSData *)value { id obj = [self objectForKey:defaultName defaultValue:value]; if ([obj isKindOfClass:[NSData class]]) { return obj; } return value; } - (NSArray *)stringArrayForKey:(NSString *)defaultName defaultValue:(NSArray *)value { id obj = [self objectForKey:defaultName defaultValue:value]; if ([obj isKindOfClass:[NSArray class]]) { for (id item in obj) { if (![item isKindOfClass:[NSString class]]) { return value; } } return obj; } return value; } - (NSInteger)integerForKey:(NSString *)defaultName defaultValue:(NSInteger)value { id obj = [self objectForKey:defaultName defaultValue:[NSNumber numberWithInteger:value]]; if ([obj isKindOfClass:[NSNumber class]]) { return [obj integerValue]; } return value; } - (float)floatForKey:(NSString *)defaultName defaultValue:(float)value { id obj = [self objectForKey:defaultName defaultValue:[NSNumber numberWithFloat:value]]; if ([obj isKindOfClass:[NSNumber class]]) { return [obj floatValue]; } return value; } - (double)doubleForKey:(NSString *)defaultName defaultValue:(double)value { id obj = [self objectForKey:defaultName defaultValue:[NSNumber numberWithDouble:value]]; if ([obj isKindOfClass:[NSNumber class]]) { return [obj doubleValue]; } return value; } - (BOOL)boolForKey:(NSString *)defaultName defaultValue:(BOOL)value { id obj = [self objectForKey:defaultName defaultValue:[NSNumber numberWithBool:value]]; if ([obj isKindOfClass:[NSNumber class]]) { return [obj boolValue]; } return value; } - (void)setSecureInteger:(NSInteger)value forKey:(NSString *)defaultName { [self setSecureObject:[NSNumber numberWithInteger:value] forKey:defaultName]; } - (void)setSecureFloat:(float)value forKey:(NSString *)defaultName { [self setSecureObject:[NSNumber numberWithFloat:value] forKey:defaultName]; } - (void)setSecureDouble:(double)value forKey:(NSString *)defaultName { [self setSecureObject:[NSNumber numberWithDouble:value] forKey:defaultName]; } - (void)setSecureBool:(BOOL)value forKey:(NSString *)defaultName { [self setSecureObject:[NSNumber numberWithBool:value] forKey:defaultName]; } @end 
+2
source

You can encrypt values ​​with a hard-coded key pair. You need to save the data as an NSData object, and you can continue to use NSUserDefaults .

This question may interest you.

0
source

Source: https://habr.com/ru/post/909051/


All Articles