1

My program connects to a server, the public key of the server is already known. The program then encrypts a AES key together with an initialization vector, and sends it to the server. The server decrypts the message and from now on AES is used to encrypt the conversation.

My question is about how to generate the IV. If I go the naive way and seed a pseudo random generator with the current time, an attacker could probably make a few very good guesses about the IV, which is of curse not what I want.

As hardware random generators are not only slow, but also not available everywhere, I'd like to go for a different approach. When the client program is first started, I let the user make a few random mouse moves, just like TrueCrypt does. I now save those "random bits" created by the mouse movement and when I need a generator, I'll use them as a seed. Of course, the random bits have to get updated every time I use them as seed. And this is my question: I thought about just saving the first few random bits generated as the new "random bits". (So they get used to initialize the random engine next time the software starts.) Now I'm not sure if this would be random enough or if pseudo random generators would show guessable patterns here. (I'd probably use std::mt19937 http://en.cppreference.com/w/cpp/numeric/random)

Edit: The chaining mode changes, so I want it to work for the mode with the "highest" requirements. Which would be CBC if I remember correctly.

Please note: The software I'm writing is purely experimental.

cooky451
  • 3,460
  • 1
  • 21
  • 39

3 Answers3

2

Use a cryptography PRNG, just like you do for the key.

On windows use CryptGenRandom/RtlGenRandom and on Linux/Unix use /dev/urandom. Those get seeded by the OS, so you don't need to take care of it.

If you really want to create your own PRNG, look into Fortuna. Don't use a Mersenne twister.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262
  • Okay, so if I use my "mouse-moving-method" together with a cryptographically secure PRNG such as Fortuna, the random numbers I'm getting are "random enough" to use them as seed the next time the program starts? Is there any known limit to this? Do I have to "refresh the randomness" by the user after x program restarts / generated seeds? – cooky451 Nov 24 '12 at 15:51
  • The main issue is that you must not emit any random numbers before you have accumulated enough initial entropy. And that's hard to estimate. – CodesInChaos Nov 24 '12 at 15:57
  • Well I mean the initial entropy shouldn't be a problem, I think random mouse movements over 30 seconds are a quite good entropy source. The question is for how long can I use the then generated random numbers as a seed before I have to ask the user again to do the mouse trick. – cooky451 Nov 24 '12 at 16:04
  • @cooky451 1) Use the system APIs. They're better than whatever you can cook up. 2) In principle a seed is good or almost unlimited amounts of data. 3) your practical problems will be reuse of random data after your persistent store gets reset to an older value. So I don't like persistent stores for this. – CodesInChaos Nov 24 '12 at 16:07
  • 1) The purpose of this project is to learn something, I do not wish to use the system APIs. I know it's easier, but the goal here is not to "get things done". 3) I don't understand. With the persistent store you mean the state of the PRNG? – cooky451 Nov 24 '12 at 16:17
  • Persisting the state of the PRNG between runs of your application is non trivial. – CodesInChaos Nov 24 '12 at 16:31
  • Why? I have to assume the computer itself is secure anyway, so I don't really see any problem with saving the generator state on the hard drive? – cooky451 Nov 24 '12 at 16:52
  • IMO this kind of persistent state is an accident waiting to happen. 1) If you use a SSD, that value can't be deleted in a reliable way => no forward secrecy, janitor attack,... 2) State reuse can happen. For example due to crashes, restores from backup, VM cloning, running the application twice at the same time,... – CodesInChaos Nov 24 '12 at 16:59
  • 1) This is not in my interest, as I said, I'm assuming the environment to be safe. 2) Hm. This could indeed be a problem. Crashes -> I'm saving a "used" flag. Running the app twice or copying it. (It'll be mobile.) -> Argh. I could xor the state with an SHA2 Hash of the system time. Any ideas? – cooky451 Nov 24 '12 at 17:09
  • 1) Just because the device is secure now, doesn't mean it'll be secure in the future. It can get stolen,... 2) you should mix in as much entropy as you can find on startup. Including the process-id and time. But don't xor in the state, pass all parts to a hashfunction. – CodesInChaos Nov 24 '12 at 17:13
  • 1) I'm assuming the device itself is encrypted, otherwise I don't safe the state anyway. ;) 2) I'm trying to keep the system-dependent parts low, so process-id is not really something I'd like to use. But okay, I think I know what to do know. Thanks. – cooky451 Nov 24 '12 at 17:20
1

You should clarify which chaining mode you plan to use. The security requirements for the initialization vector strongly depend on that.

For instance, in CBC mode the IV must be unpredictable and unique. For CTR mode, it can must only be unique, not necessarily unpredictable.

-1

Pseudo-random generators are nice for things where you don't want users to be able to predict the outcome (such as dice rolls in games), but worthless for cases where you don't want a computer to be able to compute it. For cryptography, don't use pseudo-randomness at all.

If you want randomness, you need actual random data. As you write, mouse movements are a good source for that. Given that you don't talk about /dev/random, I take it you're running on Windows, which unfortunately doesn't gather randomness while running. So you will have to do this yourself. Depening on the use case, you can run a randomness daemon at startup which keeps gathering random data and allows your program to retrieve it when it is needed, or you can ask the user to make some mouse movements when your program starts.

Or you can decide that if Windows doesn't want you to have real random data, you don't want to use Windows, but I suppose that's not an option. ;-)

Bas Wijnen
  • 1,288
  • 1
  • 8
  • 17
  • Side note: most hardware security modules (HSMs) have to use PRNGs in order to comply with cryptographic standards, e.g. FIPS 140-2, although they are usually seeded from sources of pure randomness. – Duncan Jones Nov 24 '12 at 09:33
  • 1
    Windows does gather randomness when running. – President James K. Polk Nov 24 '12 at 12:58
  • @GregS: It does? Why do programs like putty ask you to move your mouse around then? – Bas Wijnen Nov 24 '12 at 15:15
  • @Bas Wijnen Just take a look at the std::random_device implementation on Windows. – cooky451 Nov 24 '12 at 15:31
  • @cooky451: According to msdn: "The class describes a source of random numbers, preferably from a non-deterministic external device. In this implementation the values produced by default are not non-deterministic." In another source (cppreference.com) it says that "std::random_device is a uniformly-distributed integer random number generator, which produces non-deterministic random numbers, if a non-deterministic source (e.g. a hardware device) is available to the implementation." Sounds like it only works if you have a special randomness device installed, and it doesn't use mouse movements etc – Bas Wijnen Nov 24 '12 at 16:23
  • @BasWijnen http://stackoverflow.com/questions/9549357/the-implementation-of-random-device-in-vs2010 – cooky451 Nov 24 '12 at 16:31
  • @cooky451: Interesting. They must have changed that, then. Good thing they did. :-) – Bas Wijnen Nov 24 '12 at 17:23
  • Windows CryptGenRandom has been around since the 1990's. – President James K. Polk Nov 25 '12 at 01:15