Совместимость шифрования между TCL и openssl
У меня есть сценарий оболочки и сценарий tcl, использующий механизм шифрования, и я хочу, чтобы оба сценария имели одинаковый вывод шифра.
например, выходной шифр сценария tcl и сценария оболочки должен быть одинаковым. Механизм шифрования, который я хочу использовать, - это AES или DES. (и я открыт для использования любого механизма шифрования на самом деле)
Проблема в том, что оба скрипта создают разные зашифрованные тексты.
В tcl я использую следующую команду:
[aes::aes -mode cbc -dir encrypt -key 1234567891012345 hi]
и в сценарии оболочки:
echo -n "hi" | openssl enc -aes-128-cbc -nosalt -pass pass:1234567891012345
Я предполагал, что результат обеих команд будет одинаковым, но это не так. Я не предъявляю никаких опций соли, так что тот же шифр генерируется из сценария оболочки, если команда выполняется дважды.
Есть ли способ сделать один и тот же зашифрованный текст, используя разные сценарии?
1 ответ
Если вы скажете openssl enc
чтобы использовать ключевую фразу, она всегда передается через KDF, никогда не используется непосредственно в качестве ключа; с помощью -nosalt
не отключает это. (Вы можете использовать openssl enc -p
возможность увидеть, какой ключ и IV на самом деле используются.) Чтобы указать необработанный ключ, вам нужно -K
вариант.
(Обратите внимание, что openssl enc -K
Ожидается, что значение будет в шестнадцатеричном aes::aes -key
интерпретируется как необработанные двоичные данные.)
Другая проблема - отступы. Поскольку AES является блочным шифром, все входные данные должны быть дополнены до 16 байтов (размер блока AES), и существует несколько методов заполнения с различными свойствами безопасности. Tcl aes
Модуль использует простое заполнение нулями, расширяя данные на 0x00 байт.
Между тем OpenSSL использует заполнение PKCS#7 и заполняет блок значением, соответствующим размеру пэда. Например, если ваш вход составляет всего 2 байта, ему нужно 14 байтов заполнения, поэтому в соответствии с PKCS#7 каждый байт заполнения также будет иметь значение 14 (0x0E).
( man enc
говорит о PKCS#5, который является более старым документом, определяющим схему заполнения только для 8-байтовых блоков. Позже PKCS#7 определил точно такую же схему для любого размера блока.)
Для режима CBC вам также необходимо указать IV (16 байтов, равный размеру блока AES). Модуль Tcl по умолчанию использует IV со всеми нулями. Хотя CBC использует IV только для 2-го и последующих блоков, это не влияет на вывод короткого текста.
Итак, в заключение, они дадут вам идентичные результаты (используя заполнение нулями):
aes::aes -mode cbc -dir encrypt -key 1234567891012345 -hex "hi"
printf 'hi\0\0\0\0\0\0\0\0\0\0\0\0\0\0' \
| openssl enc -aes-128-cbc -nopad \
-K 31323334353637383931303132333435 \
-iv 00000000000000000000000000000000 \
| hexdump -C
Это также (используя заполнение PKCS#7):
aes::aes -mode cbc -dir encrypt -key 1234567891012345 -hex \
"hi\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e"
printf 'hi' \
| openssl enc -aes-128-cbc \
-K 31323334353637383931303132333435 \
-iv 00000000000000000000000000000000 \
| hexdump -C
Для реализации заполнения:
set data "hi"
set pad [expr {16 - ([string length $data] % 16)}]
append data [string repeat [format %c $pad] $pad]
aes::aes -mode cbc -dir encrypt -key 1234567891012345 -hex $data