2012-02-22 12 views
6

Actualmente estoy usando NSUserDefaults, pero he escuchado que Jailbreakers puede cambiar fácilmente estos valores y hacer trampa en Game Center. ¿Debería encriptar el valor que almaceno? ¿Debo usar llavero? ¿Debo almacenar el valor en binario en NSUserDefualts usando BOOL (probablemente no)? ¿Cuál es la mejor manera de almacenar un puntaje alto para evitar el pirateo y cómo se hace?¿Cuál es la mejor manera de guardar los mejores puntajes en el iPhone para evitar piratear?

Respuesta

3

Cualquier dato que necesite ser accesible solo a través de un código y debería ser seguro cabría perfectamente en KeyChain.

Si se convierte en algo más que solo un poco de datos, cifrarlo y almacenarlo en el directorio de documentos también podría hacer el trabajo. Pero si alguien realmente lo desea, desmontan su aplicación y tratan de localizar la clave de cifrado. No es fácil, pero se puede hacer.

+0

¿No hay manera para un dispositivo con jailbreak para acceder al llavero? ¿Debo todavía encriptar los datos que almaceno en el llavero usando el cifrado NSData, o está siendo almacenado en el llavero lo suficiente? – jadengeller

+0

Bueno, es posible, pero el llavero es un elemento al que solo pueden acceder las aplicaciones que comparten el mismo identificador de paquete. – rckoenes

0

Puede encriptar los valores usando un par de claves codificadas. Tendrá que guardar los datos como un objeto NSData y puede continuar usando NSUserDefaults.

Esto question te puede interesar.

2

Este es el código que estoy usando, algunos de ellos se han tomado de Internet

Tomé la idea de éste: https://github.com/matthiasplappert/Secure-NSUserDefaults


cómo utilizar

en su 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 
} 

cuando desea utilizar

[[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 

código aquí

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 
Cuestiones relacionadas