1

I have a shell script and a tcl script using encryption mechanism and want to have a same cipher output from both the scripts.

for example, the output cipher of tcl script and shell script should be the same.The encryption mechanism that I wish to use is either AES or DES. (and I am open to using any encryption mechanism as a matter of fact)

The problem is that both the scripts are producing different cipher texts.

In tcl i am using the following command :

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

and in shell script:

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

I assumed that the result of both the commands will be the same, but it isn't. I am suing no salt option so that same cipher is generated from shell script if the command is executed twice.

Is there any way to do achieve same cipher text using different scripts?

1 Answers1

2

If you tell openssl enc to use a passphrase, it is always fed through a KDF, never used directly as the key; using -nosalt doesn't disable this. (You can use the openssl enc -p option to see what key and IV is being in fact used.) To specify a raw key, you need the -K option.

(Note that openssl enc -K value is expected to be in hexadecimal, meanwhile aes::aes -key is interpreted as raw binary data.)

The other issue is padding. Since AES is a block cipher, all input data must be padded to a multiple of 16 bytes (the AES block size), and there are multiple padding methods with different security properties. The Tcl aes module uses simple zero padding, extending the data with 0x00 bytes.

Meanwhile OpenSSL uses PKCS#7 padding, and fills the block with a value matching the pad size. For example, if your input is only 2 bytes, it needs 14 bytes of padding, so according to PKCS#7 every pad byte will also have the value of 14 (0x0E).

(man enc speaks of PKCS#5, which is an older document defining the padding scheme for 8-byte blocks only. PKCS#7 later defined the exact same scheme for any block size.)

For CBC mode you also need to specify an IV (16 bytes, equal to the AES blocksize). The Tcl module uses an all-zeros IV by default. Though CBC only uses the IV for 2nd and later blocks, so it doesn't affect output for short text.

So in conclusion, these will give you identical results (using zero padding):

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

These as well (using PKCS#7 padding):

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

To implement the padding:

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
grawity
  • 501,077