Compatibilidad de cifrado entre TCL y openssl

Compatibilidad de cifrado entre TCL y openssl

Tengo un script de shell y un script tcl que utilizan un mecanismo de cifrado y quiero tener el mismo resultado de cifrado en ambos scripts.

por ejemplo, el cifrado de salida del script tcl y del script shell debería ser el mismo. El mecanismo de cifrado que deseo utilizar es AES o DES. (y, de hecho, estoy abierto a utilizar cualquier mecanismo de cifrado)

El problema es que ambos scripts producen textos cifrados diferentes.

En tcl estoy usando el siguiente comando:

[aes::aes -mode cbc -dir encrypt -key 1234567891012345 hi]

y en el script de shell:

echo -n "hi" | openssl enc -aes-128-cbc -nosalt -pass pass:1234567891012345

Supuse que el resultado de ambos comandos sería el mismo, pero no lo es. No estoy demandando ninguna opción salt para que se genere el mismo cifrado a partir del script de shell si el comando se ejecuta dos veces.

¿Hay alguna forma de lograr el mismo texto cifrado utilizando diferentes scripts?

Respuesta1

Si indica openssl encque se use una frase de contraseña, siempre se envía a través de un KDF, nunca se usa directamente como clave; El uso -nosaltno desactiva esto. (Puede usar la openssl enc -popción para ver qué clave e IV se están utilizando realmente).Para especificar una clave sin formato, necesita la -Kopción.

(Tenga en cuenta que openssl enc -Kse espera que el valor seaen hexadecimal,mientras tanto aes::aes -keyse interpreta como datos binarios sin procesar).

El otro tema es el acolchado. Dado que AES es un cifrado de bloque,todos los datos de entrada deben ser rellenadosa un múltiplo de 16 bytes (el tamaño del bloque AES) y existen varios métodos de relleno con diferentes propiedades de seguridad. El aesmódulo Tcl utiliza un relleno de ceros simple, ampliando los datos con 0x00 bytes.

Mientras tanto, OpenSSL usa relleno PKCS#7 y llena el bloque con un valor que coincide con el tamaño del pad. Por ejemplo, si su entrada tiene solo 2 bytes, necesita 14 bytes de relleno, por lo que, según PKCS#7, cada byte de relleno también tendrá el valor de 14 (0x0E).

( man enchabla de PKCS#5, que es un documento antiguo que define el esquema de relleno solo para bloques de 8 bytes. PKCS#7 posteriormente definió exactamente el mismo esquemapara cualquier tamaño de bloque.)

Para el modo CBC también es necesarioespecificar una vía intravenosa(16 bytes, igual al tamaño del bloque AES). El módulo Tcl utiliza un IV de todos ceros de forma predeterminada. Aunque CBC solo usa el IV para el segundo bloque y posteriores, no afecta la salida de texto breve.

En conclusión, estos le darán resultados idénticos (usando relleno con ceros):

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

Estos también (usando el relleno 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

Para implementar el relleno:

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

información relacionada