Ключевые данные и IV для AES в Tcl
У меня есть инструмент на основе tcl/tk, который использует сетевой пароль для аутентификации. Проблема в том, что он сохраняет пароль в журналах / истории. Поэтому цель - зашифровать пароль.
Я пытался использовать пакет aes. Но в самом начале aes::init запрашивает ключевые данные и вектор инициализации (16 байт). Итак, как генерировать IV и ключевые данные. Это какое-то случайное число? Я новичок в алгоритмах шифрования.
2 ответа
Если у вас есть пароль в журналах / истории, почему бы не исправить ошибку регистрации / хранения в первую очередь?
В противном случае есть отдельные вещи, которые вы могли бы хотеть:
Схема хеширования пароля, такая как
PBKDF2
,bcrypt
,argon2
и т. д. для безопасного хранения пароля и сравнения с ним вводимых пользователем данных. Это обычно тот случай, когда вам нужно реализовать какую-то аутентификацию с паролями на стороне сервера.Схема шифрования и защиты паролем, как AES. Вам нужен пароль для автоматической аутентификации в каком-либо сервисе, и для этого требуется какой-либо пароль в виде открытого текста.
У вас есть некоторые секретные данные, и вам необходимо хранить их в незашифрованном виде.
Если у вас есть случай 1, не используйте aes
пакет, это неправильный инструмент для работы. Если у вас есть случай 2, то aes
Пакет может помочь вам, но вы только что обменялись проблемой сохранения пароля в секрете с другой проблемой сохранения ключа в секрете (не большой выигрыш). Так что единственный жизнеспособный случай, когда aes
это вариант может быть 3.
Предположим, вам нужно хранить некоторые секретные данные в обратимом виде, например, случай 3 сверху.
AES имеет несколько возможных режимов работы, наиболее распространенными из которых являются: ECB
, CBC
, OFB
, GCM
, CTR
, Пакет Tcllib просто поддерживает ECB
а также CBC
, и только CBC
(который используется по умолчанию) - это действительно вариант для использования. Посетите Википедию для примера, почему вы никогда не должны использовать ECB
Режим.
Теперь вернемся к вашему актуальному вопросу:
Вектор инициализации (IV)
Это случайное значение, которое вы выбираете для каждого шифрования, это не секрет, вы можете просто опубликовать его вместе с зашифрованными данными. Выбор случайного IV помогает различать два зашифрованных блока, даже если вы используете один и тот же ключ и открытый текст.
Секретный ключ
Это также случайное значение, но вы должны хранить его в секрете, так как оно может использоваться для шифрования и дешифрования. У вас часто есть один и тот же ключ для нескольких шифрований.
Где взять хорошую случайность?
Если вы используете Linux, BSD или другие Unixoid системы, просто читайте байты из /dev/urandom
или используйте обертку для getrandom()
, НЕ используйте Tcls expr {rand()}
или аналогичные генераторы псевдослучайных чисел (PRNG). На Windows TWAPI и тому CryptGenRandom
Лучше всего было бы использовать функцию, но, к сожалению, в нее не входит высокоуровневая оболочка Tcl.
Этого достаточно?
Зависит. Если вы просто хотите скрыть немного открытого текста от поверхностного взгляда, может быть. Если у вас есть злоумышленники, манипулирующие вашими данными или активно пытающиеся взломать вашу систему, тем более. На простом AES-CBC есть много вещей, которые вы можете сделать неправильно, и даже эксперты ошиблись (читайте о проблемах SSL/TLS 1.0 с AES-CBC).
Заключительные слова: если вы новичок в алгоритмах шифрования, убедитесь, что вы понимаете, что вы хотите и нужно защищать, есть много подводных камней.
Если я читаю вики-страницу Tcler на aes, я вижу, что зашифрую, выполнив это:
package require aes
set plaintext "Some super-secret bytes!"
set key "abcd1234dcba4321"; # 16 bytes
set encrypted [aes::aes -dir encrypt -key $key $plaintext]
и я расшифровываю, делая:
# Assuming the code above was run...
set decrypted [aes::aes -dir decrypt -key $key $encrypted]
Обратите внимание, что расшифрованный текст имеет NUL (ноль) байтов, добавленных в конце (8 из них в этом примере), потому что алгоритм шифрования всегда работает с блоками по 16 байтов, и если вы работаете с текстом не-ASCII, то encoding convertto
а также encoding convertfrom
может быть необходимо.
Вам не нужно использовать aes::init
непосредственно, если вы не делаете масштабное потоковое шифрование. Ваш вариант использования не звучит так, как будто он нуждается в подобных вещах. (Ключевыми данными является ваш "секрет", а вектор инициализации является чем-то стандартизированным, что обычно вам не нужно устанавливать.)