3

I need to write a simplified encryption API that can easily deal with symmetric encryption, either by using a random generated key or a password-derived key.

The password generation is performed with the PKCS5_PBKDF2_HMAC() function from the OpenSSL library and using EVP_sha256() as hashing algorithm and a random generated 16-byte salt.

The symmetric encryption is performed with the OpenSSL EVP API.

My question is: how (in)secure is it to use the password derivation salt also as the IV for encryption?

The reason behind this question is that this will allow me to simplify the API and the output stream in the following way:

  • for the encryption routine, a user would have to provide either the password or the secret key; based on whichever is provided, the code can decide if a key needs to be derived from the password or use the provided key as it is;
  • similarly, for the decryption routine, a user would have to provide either the password or the secret key; based on whichever is provided, the key could be re-derived from the password and the IV, which is also acting as a password salt (and is put first in the output stream, right before the ciphertext);
  • the output stream will consist only of the IV concatenated with the ciphertext, eliminating a separate salt;
  • the output stream will be the same for a random generated key or a password-derived key.

Note: the API automatically takes care of the salt/IV generation, which is randomly generated for each encryption session, so even if a password is reused, the key is guaranteed to be different.

Thank you in advance for your answers.

Silviu
  • 33
  • 6
  • Does anybody have a clue about this? – Silviu Jun 06 '13 at 11:51
  • Did you get your answer? if i understand correctly, you proposed on first generating one random number, then deriving both salt and IV from the same seed random number. this way instead of transmitting `(salt,IV,cypher)` , you transmit 2-tuple `(rand,cypher)`. receiver derives salt and IV from rand. Is this correct? – inquisitive Dec 01 '13 at 15:26
  • No answer yet :) You got it right, except that I don't derive anything. I just use the same rand value for both salt and IV directly. Of course, the length is as large and as random as PBKDF2 and the chosen cipher mode require (i.e. no counter, just plain random). – Silviu Jun 02 '15 at 15:17
  • Take a look at the [RNCryptor specification](https://github.com/RNCryptor/RNCryptor-C#rncryptor-data-formats). Infant you might consider just using RNCryptor, it has support for multiple [languages/platforms](https://github.com/RNCryptor). – zaph Dec 21 '15 at 20:58

1 Answers1

1

As it happens, I've run into pretty much exactly the same scenario while working on one of my own projects (where a message is encrypted in CBC-mode with a random IV, and the user can either specify a key or a textual password).

Similar questions are discused here and here. To summarize: the purpose of an IV is to ensure that ciphertext remains unique even if the key is reused. As long as you're generating a new IV per message like you said you are, the source of the key doesn't matter as much. Which means you're probably safe reusing the salt as the IV, as far as anyone knows right now. It doesn't even seem like it would even make sense for it to be an issue, because the salt gets put through a cryptographic hash before deriving the key in a different way; as long as you use a good hashing function in PBKDF2 (i.e. SHA-256 as mentioned above), a key so derived is indistinguishable from one which was randomly generated, which in this case it might have been.

However, people uncover unexpected things in the world of cryptanalysis all the time, and straight-up reusing the same data in two places is considered A Bad Thing in principle even if we don't know of any practical problems right this minute. Should you actually be worried about this? At my level of knowledge on cryptanalysis, I'm somewhere between "maybe" and "I don't know," which is a little too much uncertainty for my tastes, so I'm going with the "technically safer" course of action, which is generating separate IV and salt values. Transmitting both the salt and the IV is a perfectly cromulent security practice, and you have nothing to lose if the user directly inputs the key and the salt goes unused.

Community
  • 1
  • 1
  • 1
    As well as transmitting the PBKDF iteration count and a version indicator. – zaph Dec 21 '15 at 21:00
  • True, though that seems a bit beyond the scope of the original question. – Dizzy H. Slightly Voided Dec 21 '15 at 23:50
  • 1
    Yes and that is why there are so many security flaws. The version is most important when a change needs to be made such as adding an iteration count or authentication. The iteration count so it can be updated as future needs demand. A lot of the security lasts a long time, to long if it can't be updated. You see all to often DES being used and the comment that it can't be changed, a version lets it be updates, that is why https and TLS can be updated and stay secure. It is all very simple to implement, just pre-pend it to the encrypted data. – zaph Dec 22 '15 at 00:59
  • Somehow, I missed those results in my research and they were created before I asked here. In general, I also support crypto agility (versioning algorithms and protocols in messages) as often as possible. Except in the context that triggered this question it was simply not doable, for backward compatibility reasons: messages encrypted with the new API had to fit into existing structures that only had space for an IV next to the actual ciphertext. – Silviu Dec 22 '15 at 20:36
  • This is the part where I'd start wondering who decided it was absolutely necessary to use a system that doesn't have versioning ;) So you're saying the API wouldn't let you pretend that a separate salt is part of the ciphertext? (16-byte salt, 128-byte ciphertext, "oh yes this ciphertext is 144 bytes long ...") – Dizzy H. Slightly Voided Dec 23 '15 at 19:24
  • API was just half of the story. The other half is that the new ciphertext had to fit existing network protocols, with fixed headers. And, to make it even nicer, at the other end of the protocol there usually was another machine whose code was not under my control. Now try to simplify the API for non-security-aware programmers for which a key = a password and still be backwards compatible with the message format. – Silviu Dec 26 '15 at 22:00