-1

I downloaded the openssl-1.0.2l.tar.gz source package from https://www.openssl.org/source/ and made a fresh x64 build for Windows. I use the openssl application to encrypt a file using the following command:

openssl enc -aes-128-cbc -a -salt -in data.txt -kfile key.txt -out encrypted.txt -p

Now, I would like to consume the encrypted file in a .NET application (written in C#). I read the encrypted file (which is encoded using Base64, because of the -a switch), decode it, and extract the first 16 bytes in order to get the salt that was generated by OpenSSL... this works fine so far; the salt is prefixed with Salted__, the following 8 bytes are the actual salt value.

What I have learned so far is that OpenSSL reads the first line of the given key file and uses that string for the passphrase. The actual key and initialization vector gets derived from the passphase, the salt and some hashing, which is not officially documented.

The -p switch gave me the key and initialization vector that is used for the encryption, but I would like to know, how I can reproduce that data from the known passphrase and the salt... Everything I have tried gives me key and vector data that is different from what the openssl application gave me.

Of course, I already found similar questions (and answers) at stackoverflow and crypto.stackexchange, but none of the solutions seem to work, or are related to aes-256-cbc... not sure, if that makes a difference?

What needs to be done to properly derive the key and initialization vector?

Matze
  • 5,100
  • 6
  • 46
  • 69

1 Answers1

5

It's documented here or here, but you have to know what to look for. The function is called EVP_BytesToKey and uses a hash function to stretch the salt and password into a key and IV.

Note that OpenSSL switched from MD5 to SHA-256 in version 1.1.0 (source). The iteration count is 1 and the output size depends on the chosen key size and block size.

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
  • Thanks, but your answer is even less specific than the information I already found... what particular digest is used by default in version `1.0.2` or newer; is it `MD5`, `SHA1`, or `SHA256`? – Matze Aug 10 '17 at 19:02
  • 2
    The [documentation](https://www.openssl.org/docs/manmaster/man1/enc.html) says: *"The default digest was changed from MD5 to SHA256 in Openssl 1.1.0."*. So, your version should still use MD5 by default. – Artjom B. Aug 10 '17 at 19:13
  • If the iteration count is `1` then the derived key would be `MD5(password + salt)`, wouldn´t it? The derived key would be 16 bytes long; what does that mean for `key` and `iv`; would they be equal? – Matze Aug 10 '17 at 19:49
  • 1
    No, you have to distinguish the count from the expansion. `D_i` can be computed from `D_(i-1)`. The hash iteration is separate from that. Anyway, I suggest that you look for a C# implementation of that like this one: https://stackoverflow.com/a/8011654/1816580 – Artjom B. Aug 10 '17 at 20:03