Получите соль от пароля - Насколько (в) это безопасно? - PullRequest
1 голос
/ 10 марта 2019

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

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

Для моего программного обеспечения пользователь должен вводить только пароль (означает: нет имени пользователя, нет соли, нет любимого животного или цвета).

Теперь моя идея заключалась в получении соли из пароля (например, с использованием первых 16 байтов SHA-256).

Мои вопросы:

  • Насколько (не) безопасна эта реализация?
  • Каков обычный способ шифрования данных с использованием только пароля и будет лучшей альтернативой?

Что не является цельюна этот вопрос:

  • Где хранить соли
  • Безопасные алгоритмы и реализация криптографии (конечно, я не реализовал криптографию самостоятельно)
  • Архитектурные улучшения (nopЯ не хочу глобальную базу данных для хранения вещей)

Ответы [ 2 ]

0 голосов
/ 20 марта 2019

Во-первых, я настоятельно рекомендую не разрабатывать новые форматы шифрования, если вы можете помочь. Это очень сложно сделать правильно. Если вам нужен формат шифрования, который соответствует тому, что вы описываете, см. JNCryptor , который является реализацией формата RNCryptor . Формат RNCryptor разработан именно для этой проблемы, поэтому спецификация является хорошим источником информации о том, как вы можете создать свой собственный, если вы не хотите использовать его напрямую. (Я автор RNCryptor.)

См. Также libsodium . Это лучший формат шифрования, чем RNCryptor по различным техническим причинам, но его сложнее установить и использовать правильно. Для libsodium есть несколько привязок Java .

Когда вы говорите «конечно, я не реализовывал криптографию сам», это то, что вы делаете. Крипто-схемы - это больше, чем просто код AES. Решение о том, как генерировать соли новым способом, - это реализация крипто. Есть много способов собрать безопасные примитивы (например, соли) простыми способами и сделать их дико незащищенными. Вот почему вы хотите использовать что-то устоявшееся.

Ключевым выводом является то, что вы храните соль с данными. Я знаю, ты сказал, что дело не в хранении соли, а в том, как ты это делаешь. Самый простой способ сделать это - просто приклеить соль к началу текста шифра и сохранить его. Тогда вы просто читаете соль из шапки. Точно так же вы можете положить все это в конверт, если это более удобно. Что-то простое, как JSON:

{ "salt": "<base64-salt>",
  "data": "<base64-data>" }

Это не самый эффективный способ хранения данных, но он простой, стандартный и безопасный.

Помните, соли не являются секретами. Хорошо, что каждый может читать соль.


Хорошо, хватит о том, как сделать это правильно. Давайте вернемся к вашему актуальному вопросу.

Ваше соленое предложение не является солью. Это просто немного другая функция хеширования. Смысл в том, что если один и тот же пароль используется дважды (без намерения быть одним и тем же паролем), то они будут иметь разные хэши. Ваша схема не справляется с этим. Если я использую тот же подход, что и вы, и выбираю тот же пароль, что и ваш, то хеш будет таким же. Радужные столы выигрывают.

Способ, которым вы исправляете, используя статическую соль, а не модифицированную хеш-функцию. Вы должны выбрать соль, которая представляет вашу систему. Мне обычно нравится обратный DNS для этого, потому что это приводит к уникальности. Например: «com.example.mygreatapp». Кто-то, естественно, выберет «org.example.ourawesomedb». Вы также можете выбрать длинную случайную строку, но важна уникальность, поэтому мне нравится обратный DNS. (Случайные строки заставляют людей думать, что соль - это секрет, а соль - , а не - секрет.)

Вот и вся система; просто выберите постоянную соль, уникальную для вашей системы. (Если бы у вас было имя пользователя, вы бы добавили имя пользователя к соли. Это стандартный способ построения детерминированной соли.)

Но для хранения файлов я бы никогда так не поступил.

0 голосов
/ 20 марта 2019

Для шифрования данных требуется ключ , а не пароль. Есть ключ-функции-вывода для получения ключа от пароля пользователя.

Соль может использоваться для хеширования пароля, но не может использоваться для шифрования данных. Однако для шифрования существует аналогичная концепция: случайные значения называются IV или Nonce и хранятся вместе с зашифрованными данными.

Лучшее, что вы можете сделать, это

  1. используйте функцию получения ключа с солью, чтобы получить ключ от пароля.
  2. Полученный ключ позволяет зашифровать данные.
  3. В этом случае соль может храниться в зашифрованном контейнере данных (IV уже есть), поэтому нет необходимости в глобальной базе данных.

Чтобы ответить на ваш первоначальный вопрос: извлечение соли из пароля сводит на нет все цели соли, она просто становится более сложной хеш-функцией.

...