Совместимость шифрования между TCL и openssl

Совместимость шифрования между 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

Я предполагал, что результат обеих команд будет одинаковым, но это не так. Я использую опцию no salt, чтобы тот же шифр генерировался из скрипта оболочки, если команда выполняется дважды.

Есть ли способ получить один и тот же зашифрованный текст, используя разные скрипты?

решение1

Если вы указываете openssl encиспользовать парольную фразу, она всегда передается через KDF и никогда не используется напрямую в качестве ключа; использование -nosaltне отключает эту функцию. (Вы можете использовать эту openssl enc -pопцию, чтобы увидеть, какой ключ и IV фактически используются.)Чтобы указать необработанный ключ, вам понадобится опция -K.

(Обратите внимание, что openssl enc -Kожидаемое значение будетв шестнадцатеричном формате,в то время как aes::aes -keyинтерпретируется как необработанные двоичные данные.)

Другая проблема — это заполнение. Поскольку AES — это блочный шифр,все входные данные должны быть дополненык кратному 16 байтам (размер блока AES), и существует несколько методов заполнения с различными свойствами безопасности. aesМодуль Tcl использует простое заполнение нулями, расширяя данные на 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

Связанный контент