Последствия для безопасности хранения пароля в Settings.bundle и получения с CFPreferencesCopyAppValue - PullRequest
10 голосов
/ 08 августа 2009

Извиняюсь за кажущуюся очевидность этого вопроса, но по какой-то причине я не смог найти окончательного ответа в документации Apple о том, где и как хранится информация о пароле Settings.bundle. Мой вопрос: если мне нужно сохранить некоторые учетные данные для приложения, и я использую Settings.bundle, чтобы пароль вводился в текстовое поле PSTextFieldSpecifier в области настроек Apple с IsSecure = YES, а затем я получаю доступ к значению из своего приложения, используя CFPreferencesCopyAppValue, никогда не записывая его в NSUserDefaults и только отправляя его по сети надежно, насколько безопасен этот метод хранения и поиска по сравнению с хранением и получением пароля с помощью цепочки для ключей в моих собственных настройках приложения? Спасибо за ваш вклад.

Ответы [ 3 ]

8 голосов
/ 30 августа 2011

Не сохраняйте пароль пользователя в комплекте настроек.
Это не безопасно.

Помните, что вам не нужно знать, что такое оригинальный пароль, вам нужно знать, соответствует ли введенный пользователем пароль тому, что соответствует исходному паролю. Правильный способ работы с паролями в iOS - либо

  • Используйте брелок, как уже упоминали другие
  • Создание криптографической односторонней хеш-функции с использованием SHA-512 или другого шифрования и сохранение полученного хеша и соли в NSUserDefaults

Из этих опций шифрование пароля и сохранение хеша + соли является наиболее простым. Вот что вы делаете, чтобы сохранить пароль:

  1. Получить пароль от пользователя
  2. Создать случайное значение соли
  3. Создать хеш-код только для форварда, используя SHA-512 и случайное значение соли
  4. Сохраните полученное значение хэша и соли в NSUserDefaults - эти значения не могут использоваться хакерами для определения исходного пароля, поэтому нет необходимости хранить их в безопасном месте.

Теперь, когда пользователь вводит свой пароль, и вы должны проверить, верен ли он, вот что вы делаете:

  1. Получить пароль от пользователя
  2. Получите ранее сохраненное значение хеш + соли из NSUserDefaults
  3. Создайте хэш-функцию только для пересылки, используя ту же однонаправленную хеш-функцию, которую вы использовали для шифрования исходного пароля - передавая ему пароль и значение соли из NSUserDefaults
  4. Сравните полученный хеш с тем, который хранился в NSUSerDefaults. Если они совпадают, то пользователь ввел правильный пароль.

Вот код для генерации соли и прямого хэша:

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];
}

Код для этого примера был найден здесь: http://blog.securemacprogramming.com/2011/04/storing-and-testing-credentials-cocoa-touch-edition/

8 голосов
/ 08 августа 2009

CFPreferencesCopyAppValue - это просто базовый способ доступа к той же информации, которую вы получаете при использовании NSUserDefaults. С точки зрения безопасности, функции точно такие же. То есть он не зашифрован. Это безопасно только в том смысле, что оно скрыто. «Правильный» ответ - использовать цепочку для ключей.

В противовес этому то, что многие приложения используют NSUserDefaults для хранения паролей. Можно утверждать, что если пароль не контролирует доступ к информации любого значения, то попытка использования цепочки для ключей не стоит. Это подводит меня ко второму аргументу в пользу использования безопасного поля в приложении «Настройки»: API цепочки для ключей отвратителен, и, по моему опыту, по крайней мере, написание безошибочного кода довольно сложно.

3 голосов
/ 08 августа 2009

Связка ключей на iPhone будет самой безопасной, если только вы не используете пользовательское шифрование, что очень сложно сделать (и экспортировать). NSUserDefaults не считается безопасным.

...