Obecnie używam NSUserDefaults, ale słyszałem, że Jailbreakers mogą łatwo zmienić te wartości i oszukać w Game Center. Czy powinienem zaszyfrować wartość, którą przechowuję? Czy zamiast tego powinienem użyć keychain? Czy powinienem przechowywać wartość binarną w NSUserDefualts używając BOOL (prawdopodobnie nie)? Jaki jest najlepszy sposób przechowywania najlepszych wyników, aby zapobiec włamaniom i jak to się robi?Jaki jest najlepszy sposób na zapisywanie najlepszych wyników na telefonie iPhone, aby zapobiec atakom hakerów?
Odpowiedz
Wszelkie dane, które muszą być dostępne tylko za pomocą kodu i powinny być bezpieczne, idealnie pasują do urządzenia KeyChain.
Jeśli stanie się to więcej niż tylko trochę danych, można je również zaszyfrować i zapisać w katalogu dokumentów. Ale jeśli ktoś naprawdę chce, demontuje twoją aplikację i próbuje zlokalizować klucz szyfrowania. Nie jest to łatwe, ale można to zrobić.
Można szyfrować wartości za pomocą zakodowanej pary kluczy. Będziesz musiał zapisać dane jako obiekt NSData
i możesz nadal używać NSUserDefaults
.
Ten numer question może Cię zainteresować.
Jest to kod używam, niektóre z nich zostały zaczerpnięte z internetu
wziąłem pomysł z tego: https://github.com/matthiasplappert/Secure-NSUserDefaults
jak używać
w 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
}
jeśli chcesz użyć
[[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
kod tutaj
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
- 1. Jaki jest najlepszy sposób przechowywania nazwy użytkownika i hasła na telefonie iPhone?
- 2. Jaki jest najlepszy sposób na wdrożenie "timera"?
- 3. Pobieranie obrazów i zapisywanie lokalnie na telefonie iPhone Aplikacja Phonegap
- 4. Jaki jest najlepszy sposób na naukę Erlanga?
- 5. Jaki jest najlepszy sposób na skopiowanie listy?
- 6. Jaki jest najlepszy sposób na seed srand()?
- 7. Jaki jest najlepszy sposób na naukę CUDA?
- 8. Jaki jest najlepszy sposób sprawdzenia zestawu wyników IQueryable jest pusty?
- 9. Jaki jest najlepszy sposób przechowywania/obliczania wyników użytkowników?
- 10. Java IDE * na * telefonie iPhone?
- 11. Zapisywanie wyników prognozowania na CSV
- 12. W jaki sposób zapobiec atakom typu brute force na usługi danych RESTful
- 13. Rozpoznawanie mowy na telefonie iPhone
- 14. Jaki jest najlepszy sposób przesyłania strumieniowego na żywo przez kamerę iPhone na serwer multimediów?
- 15. Jak można zapobiec fałszywym wysokim wynikom na globalnej liście wyników?
- 16. Najlepszy sposób na zapisywanie danych w aplikacji Java?
- 17. Zainstaluj aplikację webapp na ekranie głównym na telefonie iPhone?
- 18. Jaki jest najlepszy sposób wykonywania jQuery .change()
- 19. Jaki jest najlepszy sposób rejestrowania błędów/zdarzeń w aplikacji na telefon iPhone?
- 20. Jaki jest najlepszy sposób na zapisanie zawartości tablicy ArrayList?
- 21. Jaki jest najlepszy sposób na porównywanie datownika w Bash?
- 22. Jaki jest najlepszy sposób na wprowadzenie logowania do usługi sieciowej?
- 23. Jaki jest najlepszy sposób na próbkowanie/profilowanie aplikacji PyObjC?
- 24. jaki jest najlepszy sposób na zmianę pochodzenia Git repo?
- 25. Jaki jest najlepszy sposób na przetasowanie tablicy w Perlu?
- 26. jaki jest najlepszy sposób zastosowania maski do EditText na Androida?
- 27. Dla zbioru danych SAS, jaki jest najlepszy sposób, aby zapobiec blokowaniu dla wielu użytkowników dostępu
- 28. Jaki jest najlepszy sposób na uzyskanie liczb losowych w NumPy?
- 29. Jaki jest najlepszy sposób na zastąpienie pliku remote.origin.url w Git?
- 30. Jaki jest najlepszy sposób na uniknięcie wyjątku NoSuchElementException w Selenie?
Czy nie ma sposobu na jailbroken urządzenia dostępu do pęku kluczy? Czy nadal powinienem szyfrować dane, które przechowuję w pęku kluczy za pomocą szyfrowania NSData, lub czy jest ono wystarczająco przechowywane w pęku kluczy? – jadengeller
Cóż, mogą, ale pęku kluczy element jest dostępny tylko dla aplikacji, które mają ten sam identyfikator pakietu. – rckoenes