For a password storing plugin (written in C) for Rockbox I need to generate initialization vectors.
The problem is that I don't have a good source of randomness. The Rockbox-supplied random() is not a cryptographic RNG. And I've got hardly any sources of randomness I can access (no mouse movements, ... on an IPod running Rockbox).
The key is currently derived via PBKDF2 from a user-supplied password and a salt (which is a constan开发者_开发技巧t prefix + some data from random()). I think the pseudo-random data should be good enough for a salt with 10000 iterations of PBKDF2.
However, where do I take my initialization vector from? Is it OK if I take some semi-random data (time + random()) and SHA that, say, 10000 times? Should I take arc4random with a seed taken from random()?
Do I even need an IV if I effectively never use the same key twice (the salt is recomputed every time the stored data is changed)? What's the best way to deal with situations like these?
Edit: Just a single user (me, owning the IPod), encryption algorithm: AES-CBC 256 bit. The file just stores a site/account/password list for various websites. It is rarely modified (whenever I create a new account on a website), when that happens a new salt and a new IV is generated.
Generally speaking, with CBC, the IV MUST be random and uniform. "Non-repeating" is not sufficient. To be more precise, the whole point of CBC is to avoid the situation where the same data block is fed twice to the underlying block cipher. Hence, the condition is that if you encrypt two messages with the same key, then the difference of the two IV must be uniformly random. With a 128-bit block cipher such as the AES, the probability that the same block is obtained twice is sufficiently low as to be neglected -- as long as the IV is randomly chosen with uniform probability over the whole space of 128-bit values. Any structure in the IV selection (such as reusing the same IV, using a counter, or a low-quality random generator) increases that probability, because you are encrypting data which has itself a lot of structure.
There is a bright side to that: if you never use the same key twice, then you can tolerate a fixed IV. But that is a strong "never".
"Non-repeating IV" is not a good enough property with CBC. However, there are some encryption modes which can use non-repeating IV. In particular, have a look at EAX and GCM. The trick here is that those mode use the provided IV in a custom PRNG which uses the encryption key; this transform the non-repeating IV (e.g. a counter, or a "random value" of low quality) into something which, from a cryptographic point of view, looks random enough. Do not try to build your own PRNG ! These things are subtle and there is no sure way to test the quality of the result.
The IV does not need to be random, it just needs to be unique for a given pair of key and data (assuming we are talking about an IV for CBC).
So random() should be okay for this purpose.
GREAT NEWS! The initialization vector doesn't need to be random, it just needs to be different for every encryption. So you can use the user's name as the salt. If you use both the user's name and the time then an attacker won't be able to detect password reuse.
精彩评论