Score:2

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

sa flag

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.)

Score:1
my flag

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.

Score:0
in flag

The big issue with your scheme is that you haven't specified how the key is derived from a password. Generally you should avoid password based encryption, as the ciphertext may be analyzed offline. That also means that the password can be guessed using parallel computations. Testing for a correct guess is usually very easy, and generally encryption schemes should not rely on the difficulty of testing if a key is correct or not.

Preferably you should use a different method of encryption. For instance, you could use asymmetric / hybrid encryption with a public key, and then use a securely stored private key once decryption is necessary.


If you cannot go around using password based encryption then you should try and use a PBKDF - a password based key derivation function - to derive the key. Sometimes this is also called a password hash, so maybe you're already planning to doso. To do that you'd need to salt the password and derive a randomized key. This key "stretches" the entropy within the password by using a work factor (an iteration count).

If you then want to encrypt multiple values with the same key then you can indeed use your scheme or the scheme that is proposed in the other answer.

mangohost

Post an answer

Most people don’t grasp that asking a lot of questions unlocks learning and improves interpersonal bonding. In Alison’s studies, for example, though people could accurately recall how many questions had been asked in their conversations, they didn’t intuit the link between questions and liking. Across four studies, in which participants were engaged in conversations themselves or read transcripts of others’ conversations, people tended not to realize that question asking would influence—or had influenced—the level of amity between the conversationalists.