Как реализовать защиту паролем для отдельных файлов?
Я пишу небольшое настольное приложение, которое должно быть способно зашифровать файл данных и защитить его паролем (то есть необходимо ввести правильный пароль для расшифровки). Я хочу, чтобы зашифрованный файл данных был автономным и переносимым, поэтому аутентификация должна быть встроена в файл (или я так полагаю).
У меня есть стратегия, которая кажется работоспособной и логичной, основанной на том, что я знаю (которой, вероятно, достаточно, чтобы быть опасной), но я понятия не имею, хороший ли это дизайн или нет. Так скажи мне: это безумие? Есть ли лучший / лучший способ сделать это?
- Шаг 1: пользователь вводит простой текстовый пароль, например, "MyDifficultPassword"
- Шаг 2. Приложение хэширует пароль пользователя и использует это значение в качестве симметричного ключа для шифрования / дешифрования файла данных. например, "MyDifficultPassword" -> "HashedUserPwdAndKey".
- Шаг 3: приложение хэширует значение хэширования с шага 2 и сохраняет новое значение в заголовке файла данных (т. Е. Незашифрованная часть файла данных) и использует это значение для проверки пароля пользователя. например, "HashedUserPwdAndKey" -> "HashedValueForAuthentication"
По сути, я экстраполирую общепринятый способ реализации паролей веб-сайта (когда вы не используете OpenID, то есть), который заключается в том, чтобы хранить (соленый) хеш пароля пользователя в вашей БД и никогда не сохранять действительный пароль., Но поскольку я использую хешированный пароль пользователя для симметричного ключа шифрования, я не могу использовать то же значение для аутентификации. Поэтому я снова хэширую его, в основном трактую как обычный пароль, и сохраняю значение с двойным хэшированием в файле данных. Таким образом, я могу перенести файл на другой компьютер и расшифровать его, просто введя свой пароль.
Так достаточно ли безопасен этот дизайн, или безнадежно наивен, или где-то посередине? Спасибо!
РЕДАКТИРОВАТЬ: уточнение и последующий вопрос о: соль.
Я думал, что соль должна держаться в секрете, чтобы быть полезной, но ваши ответы и ссылки подразумевают, что это не так. Например, эта спецификация, связанная erickson (ниже), гласит:
Таким образом, определение ключа на основе пароля, как определено здесь, является функцией пароля, соли и числа итераций, где последние две величины не должны храниться в секрете.
Означает ли это, что я мог бы хранить значение соли в том же месте / файле, что и хешированный ключ, и при этом быть более безопасным, чем если бы я вообще не использовал соль при хешировании? Как это работает?
Немного больше контекста: зашифрованный файл не предназначен для совместного использования или расшифровки другими, это действительно однопользовательские данные. Но я хотел бы развернуть его в общей среде на компьютерах, которые я не полностью контролирую (например, на работе), и могу перенести / переместить данные, просто скопировав файл (чтобы я мог использовать его дома, на разных рабочие станции и т. д.).
5 ответов
Генерация ключей
Я бы рекомендовал использовать распознанный алгоритм, такой как PBKDF2, определенный в PKCS #5 версии 2.0, чтобы сгенерировать ключ из вашего пароля. Он похож на описанный вами алгоритм, но способен генерировать более длинные симметричные ключи для использования с AES. Вы должны быть в состоянии найти библиотеку с открытым исходным кодом, которая реализует генераторы ключей PBE для различных алгоритмов.
Формат файла
Вы можете также рассмотреть возможность использования синтаксиса криптографических сообщений в качестве формата для вашего файла. Это потребует некоторого изучения с вашей стороны, но опять же есть существующие библиотеки для использования, и это открывает возможность более гладкого взаимодействия с другим программным обеспечением, таким как почтовые клиенты с поддержкой S/MIME.
Проверка пароля
Что касается вашего желания сохранить хэш пароля, если вы используете PBKDF2 для генерации ключа, вы можете использовать для этого стандартный алгоритм хеширования паролей (большая соль, тысяча раундов хеширования) и получать разные значения.
Кроме того, вы можете вычислить MAC для содержимого. Столкновение хэша с паролем, скорее всего, будет полезно злоумышленнику; столкновение хеша с контентом, скорее всего, будет бесполезным. Но это позволит информировать законного получателя о том, что для расшифровки использовался неправильный пароль.
Криптографическая соль
Соль помогает предотвратить атаки предварительно рассчитанных словарей.
Предположим, у злоумышленника есть список вероятных паролей. Он может хэшировать каждый и сравнивать его с хешем пароля своей жертвы и проверять, совпадает ли он. Если список большой, это может занять много времени. Он не хочет тратить так много времени на свою следующую цель, поэтому он записывает результат в "словарь", где хеш указывает на соответствующий ввод. Если список паролей очень и очень длинный, он может использовать такие методы, как Rainbow Table, чтобы сэкономить место.
Однако предположим, что его следующая цель засолила свой пароль. Даже если злоумышленник знает, что такое соль, его предварительно вычисленная таблица бесполезна- соль меняет хэш, полученный в результате каждого пароля. Он должен повторно хэшировать все пароли в своем списке, прикрепляя соль цели к входным данным. Каждая отдельная соль требует отдельного словаря, и если будет использовано достаточно солей, у злоумышленника не будет места для хранения словарей для всех них. Торговое пространство для экономии времени больше не является опцией; злоумышленник должен вернуться к хешированию каждого пароля в своем списке для каждой цели, которую он хочет атаковать.
Так что не нужно хранить соль в секрете. Достаточно убедиться, что у злоумышленника нет предварительно вычисленного словаря, соответствующего этой конкретной соли.
Как сказал Нияз, подход звучит разумно, если вы используете качественную реализацию сильных алгоритмов, таких как SHA-265 и AES для хеширования и шифрования. Кроме того, я бы рекомендовал использовать Salt, чтобы уменьшить возможность создания словаря всех хэшей паролей.
Конечно, чтение прикладной криптографии Брюса Шнайера также никогда не ошибается.
Почему бы не использовать библиотеку сжатия, которая поддерживает файлы, защищенные паролем? В прошлом я использовал zip-файл, защищенный паролем и содержащий контент XML:}
Если вы используете алгоритм надежного хэширования (SHA-2) и алгоритм надежного шифрования (AES), то с этим подходом у вас все получится.
Действительно ли нужно сохранить хешированный пароль в файл. Разве вы не можете просто использовать пароль (или хешированный пароль) с некоторой солью, а затем зашифровать файл им. При расшифровке просто попробуйте расшифровать файл с помощью пароля + соли. Если пользователь вводит неверный пароль, расшифрованный файл неверен.
Единственные недостатки, о которых я могу подумать, это то, что если пользователь случайно ввел неправильный пароль и расшифровка идет медленно, ему приходится ждать, чтобы повторить попытку. И, конечно, если пароль забыт, расшифровать файл невозможно.