Шифрование основных данных

У меня есть вопрос по поводу основного шифрования данных. Я храню некоторые конфиденциальные пользовательские данные в базе данных Core Data SQLite. Все критические значения являются трансформируемыми, и я использую AES256 для шифрования и дешифрования "на лету", включая индивидуальный IV для каждого значения. Ключ шифрования - это хэш-пароль SHA512, выбранный пользователем. Это работает очень хорошо до сих пор.

Теперь о пароле пользователя. Когда пользователь запускает приложение, его спрашивают его пароль. Пароль хешируется с помощью SHA512 и сохраняется в связке ключей iOS. Для каждой операции записи или чтения NSValueTransformer будет получать пароль из цепочки для ключей. Если приложение закрывается, я удаляю хэш пароля из цепочки для ключей.

В моей базе данных базовых данных у меня есть специальный объект, который имеет случайное число!= 0, поскольку это единственное значение. Чтобы проверить, правильно ли пользователь ввел пароль, я извлекаю эту сущность и читаю число. Если это =! 0, я знаю, что пароль был верным, потому что при неудачном дешифровании NSValueTransformer всегда возвращает 0.

Теперь мои актуальные вопросы: считаете ли вы это хорошим подходом к шифрованию? Как еще вы будете проверять правильность введенного пароля?

Я немного обеспокоен тем, что хранение хэша пароля в цепочке для ключей во время работы приложения делает все медленнее, потому что NSValueTransformer должен постоянно обращаться к цепочке для ключей. Будет ли он достаточно безопасным, чтобы просто хранить хэш пароля в памяти, поэтому он будет удален при закрытии приложения?

2 ответа

Вы не должны использовать хэш пароля, хэши спроектированы так, чтобы быть быстрыми, поэтому (сравнительно) легко осуществить атаку методом перебора. Используйте функцию получения ключа, такую ​​как PBKDF2.

Не используйте ключ, непосредственно полученный из пароля, в качестве ключа шифрования. Если пользователь меняет пароль, вам необходимо перешифровать все данные, и резервные копии становятся бесполезными. Используйте случайно сгенерированный ключ шифрования, который вы шифруете ключом шифрования на основе пароля.

Я не очень уверен насчет хранения хеша в цепочке для ключей вместо того, чтобы просто хранить его в памяти. В прошлый раз, когда я смотрел на это, было сравнительно легко расшифровать цепочку для ключей. И каждый злоумышленник, который может прочитать память вашего работающего приложения, скорее всего, сможет отслеживать доступ к цепочке для ключей или дешифрованные данные. Просто сохраните его в памяти и обязательно сотрите память, если приложение переходит в фоновый режим и т. Д. Это, очевидно, также верно для каждого фрагмента дешифрованных данных.

[EDIT: @JeffLockhart, чтобы уточнить процедуру для главного ключа шифрования] вы генерируете случайный ключ для шифрования ваших данных, давайте назовем его ключом A. Вы можете использовать SecRandomCopyBytes для генерации ключа A, см. Пример использования CryptoExcercise от Apple. Вы используете ключ A для шифрования пользовательских данных. Чтобы сохранить ключ A, вы должны зашифровать ключ A вторым ключом B. Вам не следует использовать пароль непосредственно в качестве ключа B из-за быстрых атак методом перебора или словарной атаки. Таким образом, вы извлекаете ключ из пароля с помощью PBKDF, как в этом ответе stackru. Затем вы шифруете ключ A ключом B, например, используя CCCrypt. Вы сохраняете зашифрованный ключ A и соль, используемую для его получения. Чтобы расшифровать, пользователь вводит пароль, вы получаете ключ B, используя пароль и соль. Вы расшифровываете ключ A, используя производный ключ B. Надежда, которая проясняется.

Вы могли бы взглянуть на это:

Безопасный инкрементный магазин

Они реализовали подкласс NSIncrementalStore, который использует зашифрованную базу данных SQLite. Это замена для Apple Store SQLite. Поставляется с ценником, а также.

Другие вопросы по тегам