5
$\begingroup$

From https://wiki.openssl.org/index.php/Manual:Enc(1):

When a password is being specified using one of the other options, the IV is generated from this password.

Why does OpenSSL do this? My expectation would be that an unique IV is generated and encoded in the output message every time you invoke OpenSSL. When decrypting, OpenSSL extracts the IV and uses it.

Is there any reason to derive an IV from a password instead? Is that even safe to do? Aren't you using the same IV each time you use the password? What even is the point of using an IV if it's going to be paired to the encryption key?

$\endgroup$
3
  • 1
    $\begingroup$ Generally, the answer to ‘Why does the openssl xyz command-line tool work the way it does?’ is ‘It was convenient for one of the developers a decade or two ago during testing, and then it stuck.’ Deeper psychoanalysis of the motivation for the design decisions in it is typically an exercise in fruitilitilessness. $\endgroup$ Sep 13, 2017 at 16:13
  • $\begingroup$ While I concur generally with @Squeamish about OpenSSL in this particular case I suspect it might be because PKCS5 v1.5, which was current in the '90s when SSLeay was created, does this; see the scheme retronymed PBES1 in more current versions of PKCS5 like rfc2898. $\endgroup$ Sep 14, 2017 at 1:51
  • $\begingroup$ @dave_thompson_085: It looks like you are right. Want to turn that into an answer with citations to PKCS#5/RFC 2898 and the OpenSSL EVP_BytesToKey man page? $\endgroup$ Sep 14, 2017 at 2:50

2 Answers 2

4
$\begingroup$

If you read the manpage you referenced a bit more carfeully, you will find the following lines:

-nosalt

do not use a salt 

-salt

use salt (randomly generated or provide with -S option) when encrypting (this is the default).

and

The -salt option should ALWAYS be used if the key is being derived from a password unless you want compatibility with previous versions of OpenSSL and SSLeay.

Without the -salt option it is possible to perform efficient dictionary attacks on the password and to attack stream cipher encrypted data. The reason for this is that without the salt the same password always generates the same encryption key. When the salt is being used the first eight bytes of the encrypted data are reserved for the salt: it is generated at random when encrypting a file and read from the encrypted file when it is decrypted.

Putting this together we learn:

  • You should use a random salt, which gets used in the key derivation process (calculating the encryption key and the IV from the password)
  • If you use a salt, the key and the IV and thus the ciphertext won't be deterministic
  • Using a random salt is the default behaviour of openssl enc

You can easily check this by running

echo foo |openssl enc -aes-128-cbc -out encrypted -nosalt

and

echo foo |openssl enc -aes-128-cbc -out encrypted

In the first case, the output will be 16 bytes long (one block of AES), in the second case it will be longer, because the salt has to be stored.

$\endgroup$
2
  • $\begingroup$ Didn't you want the paragraph "The -salt option should always be used" to be part of the quote? And note 'previous' here means approximately 'from last century' -- the oldest version I have archived, 0.9.7 from 2002, has default salt. $\endgroup$ Sep 14, 2017 at 2:01
  • $\begingroup$ Obviously. Thanks for the hint @dave_thompson_085 $\endgroup$
    – mat
    Sep 14, 2017 at 7:59
1
$\begingroup$

In OpenSSL, if the enc command is used (enc.c) the generation of the IV from a password is performed alongside the derivation of the key (by the function EVP_BytesToKey: source). As they say here:

The EVP_BytesToKey(3) function provides some limited support for password based encryption. Careful selection of the parameters will provide a PKCS#5 PBKDF1 compatible implementation. However, new applications should not typically use this (preferring, for example, PBKDF2 from PCKS#5).

Therefore, it is safe to derive an IV from a password if a proper salt is used in the derivation (see RFC 2898). If a random salt is selected each time, you are not using the same IV each time you use the password.

Furthermore, it is also safe to derive key and IV from the same output of the KDF if enough randomness is already provided by the salt. That is, the size of the salt shall be already enough to ensure that is difficult for an attacker to pre-compute all the possible keys for a dictionary of passwords. Thus, it is not reasonable to split key and IV derivation just to add the burden of computing all the possible pairs (key, IV).


My next question is, why do they not use PBKDF2 for enc command with password?

$\endgroup$
4
  • 2
    $\begingroup$ This doesn't explain why a password is involved in the derivation of an IV at all. If you randomly choose a salt, you might as well have just used that salt as an IV. $\endgroup$ Sep 13, 2017 at 13:38
  • 1
    $\begingroup$ @SqueamishOssifrage Yeah that's my next question. Although my guess at the reasoning is that since we're already generating a different key per encryption, there's really no need for an IV anymore, and adding a random IV in addition to a random salt would just complicate things operationally? $\endgroup$
    – alecbz
    Sep 13, 2017 at 13:41
  • $\begingroup$ @SqueamishOssifrage I think it's just a practical choice, because in that case you would have to choose a salt big enough to contain an IV, which is a different requirement than the actual one used for the size of the salt. The minimum recommended size for the salt is 8 octets (see: tools.ietf.org/html/rfc2898#section-4.1), while the IV size depends on the block size of the underlying cipher. The KDF used for the key, instead, easily gives as many octets of 'random material' as needed, to use for both key and IV. $\endgroup$
    – gentooise
    Sep 13, 2017 at 14:46
  • $\begingroup$ Actually EVP_BytesToKey with md5, which was the default for decades, requires at least one more output block except for RC2 and classic/single-DES both of which are now totally insecure and unacceptable, and thus would not be so easy except that enc stupidly uses iteration count 1. However, release 1.1.0 (not yet widespread) changes the default hash to sha256. $\endgroup$ Sep 14, 2017 at 2:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.