Каков наилучший способ сохранить рекорды на iPhone, чтобы предотвратить взлом? - PullRequest
6 голосов
/ 22 февраля 2012

В настоящее время я использую NSUserDefaults, но я слышал, что джейлбрейкеры могут легко изменить эти значения и обмануть Game Center.Должен ли я зашифровать значение, которое я храню?Должен ли я использовать брелок вместо?Должен ли я хранить значение в двоичном виде в NSUserDefualts, используя BOOL (вероятно, нет)?Каков наилучший способ сохранить рекорд для предотвращения взлома и как это сделать?

Ответы [ 3 ]

3 голосов
/ 22 февраля 2012

Любые данные, которые должны быть доступны только с помощью кода и должны быть безопасными, идеально поместятся в цепочке ключей.

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

2 голосов
/ 22 февраля 2012

Это код, который я использую, некоторые из них взяты из интернета

Я взял идею из этого: https://github.com/matthiasplappert/Secure-NSUserDefaults


как использовать

в вашем 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
}

когда вы хотите использовать

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

код здесь

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
0 голосов
/ 22 февраля 2012

Вы можете зашифровать значения, используя жестко заданную пару ключей. Вам нужно сохранить данные как NSData объект, и вы можете продолжать использовать NSUserDefaults.

Этот вопрос может вас заинтересовать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...