Последствия для безопасности хранения пароля в Settings.bundle и получения его с помощью CFPreferencesCopyAppValue
-
12-09-2019 - |
Вопрос
Приносим извинения за кажущуюся очевидность этого вопроса, но по какой-то причине мне не удалось найти в документации Apple однозначного ответа о том, где и как хранится информация о пароле Settings.bundle.Мой вопрос:если мне нужно сохранить некоторые учетные данные для приложения, и я использую Settings.bundle, чтобы пароль вводился в текстовое поле PSTextFieldSpecifier в области настроек Apple с IsSecure = YES, а затем я получаю доступ к значению из своего приложения с помощью CFPreferencesCopyAppValue, никогда записывая его в NSUserDefaults и безопасно отправляя его только по сети, насколько безопасен этот метод хранения и извлечения по сравнению с хранением и получением пароля с использованием цепочки для ключей в настройках моего собственного приложения?Спасибо за ваш вклад.
Решение
CFPreferencesCopyAppValue
это просто основной способ доступа к той же информации, которую вы получаете при использовании NSUserDefaults
.С точки зрения безопасности функции точно такие же.То есть он не зашифрован.Оно безопасно только в том смысле, что оно скрыто.«Правильный» ответ — использовать брелок.
Противоположностью этому является то, что многие приложения используют NSUserDefaults
для хранения паролей.Вы можете возразить, что если пароль не контролирует доступ к любой ценной информации, то не стоит пытаться использовать связку ключей.Это подводит меня ко второму аргументу в пользу использования защищенного поля в приложении «Настройки»:API связки ключей ужасен, и, по крайней мере, по моему опыту, писать безошибочный код сложно.
Другие советы
Не сохраняйте пароль пользователя в пакете настроек.
Это небезопасно.
Помните, вам не нужно знать исходный пароль, вам нужно знать, вводит ли пароль, который вводит пользователь. Матчи оригинальный пароль.Правильный способ обращения с паролями в 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/
Связка ключей на iPhone будет наиболее безопасной, если только вы не используете собственное шифрование, которое очень сложно сделать (и экспортировать).NSUserDefaults не считается безопасным.