Compatibilidade de criptografia entre TCL e openssl

Compatibilidade de criptografia entre TCL e openssl

Eu tenho um script shell e um script tcl usando mecanismo de criptografia e quero ter a mesma saída de cifra de ambos os scripts.

por exemplo, a cifra de saída do script tcl e do script shell deve ser a mesma. O mecanismo de criptografia que desejo usar é AES ou DES. (e estou aberto a usar qualquer mecanismo de criptografia, na verdade)

O problema é que ambos os scripts estão produzindo textos cifrados diferentes.

No tcl estou usando o seguinte comando:

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

e em script de shell:

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

Presumi que o resultado de ambos os comandos seria o mesmo, mas não é. Não estou processando nenhuma opção salt para que a mesma cifra seja gerada a partir do shell script se o comando for executado duas vezes.

Existe alguma maneira de obter o mesmo texto cifrado usando scripts diferentes?

Responder1

Se você pedir openssl encpara usar uma senha, ela sempre será alimentada por meio de um KDF, nunca usada diretamente como chave; usar -nosaltnão desativa isso. (Você pode usar a openssl enc -popção para ver qual chave e IV estão de fato sendo usados.)Para especificar uma chave bruta, você precisa da -Kopção.

(Observe que openssl enc -Ko valor deverá serem hexadecimal,entretanto, aes::aes -keyé interpretado como dados binários brutos.)

A outra questão é o preenchimento. Como AES é uma cifra de bloco,todos os dados de entrada devem ser preenchidospara um múltiplo de 16 bytes (o tamanho do bloco AES) e existem vários métodos de preenchimento com diferentes propriedades de segurança. O módulo Tcl aesusa preenchimento de zeros simples, estendendo os dados com 0x00 bytes.

Enquanto isso, o OpenSSL usa o preenchimento PKCS#7 e preenche o bloco com um valor correspondente ao tamanho do bloco. Por exemplo, se sua entrada tiver apenas 2 bytes, ela precisará de 14 bytes de preenchimento, portanto, de acordo com o PKCS#7, cada byte de preenchimento também terá o valor 14 (0x0E).

( man encfala de PKCS#5, que é um documento mais antigo que define o esquema de preenchimento apenas para blocos de 8 bytes. PKCS#7 posteriormente definiu exatamente o mesmo esquemapara qualquer tamanho de bloco.)

Para o modo CBC você também precisaespecifique um IV(16 bytes, igual ao tamanho do bloco AES). O módulo Tcl usa um IV com zeros por padrão. Embora o CBC use apenas o IV para o segundo bloco e posteriores, isso não afeta a saída de texto curto.

Concluindo, eles fornecerão resultados idênticos (usando preenchimento zero):

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

Estes também (usando preenchimento 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 o preenchimento:

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

informação relacionada