Извините за кажущуюся очевидность этого вопроса, но по какой-то причине я не смог найти окончательный ответ в документации Apple о том, где и как хранится информация о пароле Settings.bundle. Мой вопрос: если мне нужно сохранить некоторые учетные данные для приложения, и я использую параметр Settings.bundle, чтобы пароль был введен в текстовое поле PSTextFieldSpecifier в области настроек Apple с помощью IsSecure = YES, а затем я получаю доступ к значению из своего приложения, используя CFPreferencesCopyAppValue, никогда не записывая его в NSUserDefaults и надежно отправляя его по сети, насколько безопасен этот метод хранения и извлечения по сравнению с хранением и извлечением пароля с помощью keychain в настройках моего собственного приложения? Спасибо за ваш вклад.
Последствия безопасности для хранения пароля в Settings.bundle и получение с помощью CFPreferencesCopyAppValue
Ответ 1
CFPreferencesCopyAppValue
- это просто основной способ доступа к той же информации, которую вы получаете при использовании NSUserDefaults
. С точки зрения безопасности, функции точно такие же. То есть, он не зашифрован. Он защищен только в том смысле, что он затенен. "Правильный" ответ - использовать брелок.
Считаем, что многие приложения используют NSUserDefaults
для хранения паролей. Вы можете утверждать, что, если пароль не контролирует доступ к информации любой ценности, тогда это не стоит усилий по попытке использовать цепочку ключей. Это приводит ко второму аргументу в пользу использования безопасного поля в приложении "Настройки": API-интерфейс для ключей является отвратительным, и, по моему опыту, писать код без ошибок сложно.
Ответ 2
Не сохраняйте пароль пользователя в наборе параметров.
Это не безопасно.
Помните, что вам не нужно знать, что такое оригинальный пароль, вам нужно знать, вводит ли пароль пользовательский пароль. Правильный способ обработки паролей в iOS - либо
- Используйте цепочку ключей, как упомянули другие
- Создание криптографической односторонней хеш-функции с использованием SHA-512 или другого шифрования и сохранение полученного хеша и соли в
NSUserDefaults
Из этих параметров шифрование пароля и сохранение хэш + соли на сегодняшний день является самым простым. Вот что вы делаете, чтобы сохранить пароль:
- Получить пароль от пользователя
- Создать значение случайной соли.
- Создать хеш-форвард только с использованием SHA-512 и значения случайной соли.
- Сохранять полученное значение хэша и соли в
NSUserDefaults
- эти значения не могут использоваться хакерами для определения исходного пароля, поэтому нет необходимости хранить их в безопасном месте.
Теперь, когда пользователь вводит свой пароль, и вы должны проверить, правильно ли это, вот что вы делаете:
- Получить пароль от пользователя
- Возьмите ранее сохраненное значение хэша + соль из
NSUserDefaults
- Создайте хэширование только вперед, используя одну и ту же одностороннюю хеш-функцию, которую вы использовали для шифрования исходного пароля - передав ему попытку пароля и значение соли из
NSUserDefaults
- Сравните полученный хэш с тем, который был сохранен в
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/
Ответ 3
Брелок на iPhone будет самым безопасным, если вы не используете пользовательское шифрование, что очень сложно сделать (и экспортировать). NSUserDefaults не считается безопасным.