# Generating an IV from a constant seed and predictable salt larger than the value space of the IV

I am planning to encrypt multiple values using a 16 byte IV that I'm generating from the below scheme. My seed is a 32 byte value generated from hashing a password and salt is an 8 byte counter (i.e. salt is easy to predict for an outside observer).

iv = sha256(seed, salt)[0:16]

Intuitively this should be equivalent to randomly generating IVs, as I am mapping 32 + 8 = 40 bytes of possible values seed/salt combinations into 16 bytes of possible values for the IV and I should be hitting all possible 16 bytes values since SHA256 is uniformly random with the assumption that it is a cryptographic hash function. Is this secure?

(In case it is not clear from the text itself, I plan to encrypt multiple values with the same seed and an incrementing salt.)

I am planning to encrypt multiple values using a 16 byte IV that I'm generating from the below scheme.

I will assume that you will be using the IV's for CBC mode encryption; the important property with CBC mode is that the IV's be unpredictable.

My seed is a 32 byte value generated from hashing a password and salt is an 8 byte counter (i.e. salt is easy to predict for an outside observer).

iv = sha256(seed, salt)[0:16]

This is a decent method, as long as seed remains unknown (and you use different seeds or independent salts for different encryption keys), and that may be a problem. If you first do:

seed = hash(password)

then it is easy for an attacker to check if a specific password was used (assuming he also knows the salt; you said he did). Once he stumbles on the correct password, he can then compute the salt, and then predict future iv's (which may or may not be a security issue for your application).

One obvious alternative: you already have an encryption key that already needs to be secret; why not use that? One common practice is to use:

iv = block_encrypt( key, salt )

where key is the encryption key, and block_encrypt is the underlying block cipher you're using. Yes, this gives the attacker a few known plaintext/ciphertext pairs; however if he has known plaintext encrypted (which we assume he can get), he already has lots of known plaintext/ciphertext pairs - a few more doesn't hurt.

One nice thing about this is that it can be extremely easy to implement; if we just do (where salt16 is the salt extended to 16 bytes, and the three parameters to cbc_mode_encrypt are the key, the iv and the message):

ciphertext := cbc_mode_encrypt( key, 0, salt16 || message )

then the first 16 bytes of ciphertext will be the IV, and the rest will be the encrypted message (and if you send the IV immediately before the encrypted message, you don't need to separate them). Yes, this is using a fixed 0 as the "IV" (actually, you can use anything you want, as long as it is independent of salt16); it turns out not to be an issue in this case.