2009-08-08 17 views
10

Przepraszamy za pozorną oczywistość tego pytania, ale z jakiegokolwiek powodu nie byłem w stanie znaleźć ostatecznej odpowiedzi w dokumentacji firmy Apple na temat miejsca i sposobu ustawienia .bundle informacje o haśle są przechowywane. Moje pytanie: jeśli chcę przechowywać pewne referencje dla aplikacji i używam pliku Settings.bundle, aby hasło zostało wprowadzone do pola tekstowego PSTextFieldSpecifier w obszarze Ustawienia Apple z IsSecure = YES, a następnie uzyskuję dostęp do wartości z mojej aplikacji za pomocą CFPreferencesCopyAppValue, nigdy nie wysyłając go do NSUserDefaults i tylko wysyłając go bezpiecznie przez sieć, jak bezpieczna jest ta metoda przechowywania i pobierania w porównaniu do przechowywania i pobierania hasła za pomocą łańcucha kluczy w moich własnych ustawieniach aplikacji? Dzięki za wkład.Skutki bezpieczeństwa przechowywania hasła w pliku Settings.bundle i uzyskiwaniu za pomocą CFPreferencesCopyAppValue

+0

Rozważmy przechowywania hash zamiast hasła. Zobacz moją odpowiedź poniżej. – memmons

+0

Dzięki za dobrą sugestię - o czym wspomniałem w czasie, gdy pytałem o to kilka lat temu, po prostu utknąłem przy użyciu pęku kluczy. – Halle

+0

Tak. To dobra opcja, a Apple na pewno ją ulepszyło od pierwszego zapytania. – memmons

Odpowiedz

8

CFPreferencesCopyAppValue to tylko sposób Core Foundation na uzyskiwanie dostępu do tych samych informacji, które można uzyskać podczas korzystania z NSUserDefaults. Pod względem bezpieczeństwa funkcje są dokładnie takie same. Oznacza to, że nie jest zaszyfrowany. Jest bezpieczny tylko w tym sensie, że jest zasłonięty. "Prawidłową" odpowiedzią jest użycie pęku kluczy.

Licznik do tego jest taki, że wiele aplikacji używa NSUserDefaults do przechowywania haseł. Można argumentować, że jeśli hasło nie kontroluje dostępu do informacji o dowolnej wartości, nie jest to warte wysiłku w użyciu pęku kluczy. Co prowadzi mnie do drugiego argumentu za użyciem bezpiecznego pola w aplikacji Ustawienia: interfejs API pęku kluczy jest ohydny i, przynajmniej z mojego doświadczenia, pisanie bezbłędnego kodu jest trudne.

+0

Dobrze wiedzieć, dzięki. Zamierzam trzymać się Keychaina - nie było dla mnie jasne, że informacja o Ustawieniach kończy się w tym samym miejscu co NSUserDefaults. – Halle

+2

Możesz być zainteresowany użyciem SFHFKeychainUtils: http://github.com/ldandersen/scifihifi-iphone/tree/d4298f123a06a91acbe8422ddb6164be3dbcff9e/security. Używam go do przechowywania haseł i naprawdę upraszcza korzystanie z pęku kluczy. –

+1

Zauważyłem, że kod przykładowy Apple, który ma implementację opakowania pęku kluczy do Usług pęku kluczy, jest dość łatwy do naśladowania (a następnie użycia opakowania do zarządzania pękiem kluczy w aplikacji), jeśli usuniesz kod prezentacji z widoku kontroler, o którym myślę, że większość zamieszania przychodzi z tym przykładem. – Halle

3

Brelok na iPhonie będzie najbezpieczniejszy, chyba że używasz szyfrowania niestandardowego, co jest bardzo trudne do zrobienia (i eksportu). NSUserDefaults nie jest uważany za bezpieczny.

8

Nie zapisuj hasła użytkownika w pakiecie ustawień.
To nie jest bezpieczne.

Pamiętaj, że nie musisz wiedzieć, jakie jest oryginalne hasło, musisz wiedzieć, czy hasło wprowadzone przez użytkownika pasuje do oryginalnego hasła. Prawidłowy sposób na radzenie sobie z hasłami w iOS jest albo

  • Użyj pęku kluczy, jak wspominają inni
  • Generowanie kryptograficznego jednokierunkowej funkcji skrótu za pomocą SHA-512 lub inne szyfrowanie i przechowywanie wynikowy hash i sól w NSUserDefaults

Z tych opcji szyfrowanie hasła i przechowywanie skrótu jest zdecydowanie najłatwiejsze. Oto co trzeba zrobić, aby zapisać hasło:

  1. Grab hasło od użytkownika
  2. Tworzenie losową wartość soli
  3. Tworzenie przodu tylko do mieszania za pomocą SHA-512 oraz losową wartość soli
  4. Przechowuj wynikową wartość skrótu i ​​soli w numerze NSUserDefaults - te wartości nie mogą być użyte przez hakerów do określenia oryginalnego hasła, więc nie ma potrzeby przechowywania ich w bezpiecznym miejscu.

Teraz, gdy użytkownik wprowadzi swoje hasło i trzeba sprawdzić, czy jest on poprawny, oto co trzeba zrobić:

  1. Grab hasło od użytkownika
  2. chwycić wcześniej zapisany hash + solnej wartość od NSUserDefaults
  3. Utwórz skrót do przodu tylko przy użyciu tego samego jednokierunkowej funkcji skrótu, który został użyty do zaszyfrowania hasła oryginalnego - przekazując mu usiłowanie hasło i wartość soli z NSUserDefaults
  4. Porównaj wynikowy skrót z tym, który został zapisany w NSUSerDefaults. Jeśli są takie same, wówczas użytkownik wprowadził poprawne hasło.

Oto kod, aby wygenerować sól i hash forward-only:

NSString *FZARandomSalt(void) { 
    uint8_t bytes[16] = {0}; 
    int status = SecRandomCopyBytes(kSecRandomDefault, 16, bytes); 
    if (status == -1) { 
     NSLog(@"Error using randomization services: %s", strerror(errno)); 
     return nil; 
    } 
    NSString *salt = [NSString stringWithFormat: @"%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x%2x", 
         bytes[0], bytes[1], bytes[2], bytes[3], 
         bytes[4], bytes[5], bytes[6], bytes[7], 
         bytes[8], bytes[9], bytes[10], bytes[11], 
         bytes[12], bytes[13], bytes[14], bytes[15]]; 
    return salt; 
} 

NSData *FZAHashPassword(NSString *password, NSString *salt) { 
    NSCParameterAssert([salt length] >= 32); 
    uint8_t hashBuffer[64] = {0}; 
    NSString *saltedPassword = [[salt substringToIndex: 32] stringByAppendingString: password]; 
    const char *passwordBytes = [saltedPassword cStringUsingEncoding: NSUTF8StringEncoding]; 
    NSUInteger length = [saltedPassword lengthOfBytesUsingEncoding: NSUTF8StringEncoding]; 
    CC_SHA512(passwordBytes, length, hashBuffer); 
    for (NSInteger i = 0; i < 4999; i++) { 
     CC_SHA512(hashBuffer, 64, hashBuffer); 
    } 
    return [NSData dataWithBytes: hashBuffer length: 64]; 
} 

kod na tym przykładzie, że było tutaj: http://blog.securemacprogramming.com/2011/04/storing-and-testing-credentials-cocoa-touch-edition/

Powiązane problemy