I hope you are well! I use random numbers that depend on time for my encryption. But this makes my encryption hackable... My question is how can I make randoms that are not the same every time after running the randoms and also do not use seed time. Most of the time we randomize like this: srand ( ( unsigned ) time ( 0 ) ); cout << "the random number is: " << rand() % 11; But we used time here and the hacker can understand the random numbers by having the program run time.
-
2Does this answer your question? [Cryptographically secure RNG in C++ for RSA PKCS#1 (key generation)](https://stackoverflow.com/questions/60475527/cryptographically-secure-rng-in-c-for-rsa-pkcs1-key-generation) – Alexei Levenkov Mar 10 '22 at 05:38
-
No matter how fancy you get a determined person can figure out your code. In the end a value is passed to `srand` so you find that call and work backward. If you want to pretend you're making it more secure then do something like xor the time with the pid of the program or something. I recommend you read [Why is the new random library better than std::rand()?](https://stackoverflow.com/questions/53040940/why-is-the-new-random-library-better-than-stdrand). – Retired Ninja Mar 10 '22 at 05:40
-
2Side note: it is good idea to include results of your research (i.e. what you found by https://www.bing.com/search?q=c%2B%2B+cryptographically+secure+random+generator) into the post along with explanation why it did not help. – Alexei Levenkov Mar 10 '22 at 05:40
-
Perhaps look at using a UUID to seed a crypto-RNG. It would be hard for an adversary to guess a UUID your machine will generate. Not impossible, but probably very hard. – Gene Mar 10 '22 at 05:52
-
If a hacker has access to your seed, don't they implicitly have access to the generated output? It's hard to understand how the seeding is the weak point here. – tenfour Mar 10 '22 at 11:01
2 Answers
srand
and/or rand
aren't suited to your use at all.
Although it's not 100% guaranteed, the C++ standard library provides a random_device
that's at least intended to provide access to true random number generation hardware. It has a member named entropy()
that's intended to give an estimate of the actual entropy available--but it can be implemented as a pseudo-random number generator, in which case this should return 0. Assuming entropy()
returns a non-zero result, use random_device
to retrieve as much random data as you need.
Most operating systems provide their own access to random number generation hardware. On Windows you'd typically use BCryptGenRandom. On UNIXesque OSes, you can read an appropriate number of bytes from /dev/random/
(there's also /dev/urandom
, but it's potentially non-blocking, so it could return data that's less random if there isn't enough entropy available immediately--that's probably fine if you're simulating rolling dice or shuffling cards in a game or something like that, but probably not acceptable for your purpose).

- 476,176
- 80
- 629
- 1,111
-
2`/dev/urandom` in modern UNIX implementations is cryptographically secure and perfectly applicable to use cases like this. In fact, in the current Linux kernel, `/dev/random` and `/dev/urandom` pull from the same generator and neither one blocks after the initial seeding. – Sneftel Mar 10 '22 at 09:11
-
Even if `entropy()` returns non-zero you have no guarantee about the cryptographical security of the random numbers returned by `random_device`. The behaviour is entirely implementation defined and you have to be very careful not to end up with an insecure algorithm just because someone switches to a different library implementation. – Jakob Stark Mar 10 '22 at 09:14
-
@Sneftel I totally agree. It feels like this is an ongoing debate since decades. See [here](https://crypto.stackexchange.com/questions/41595/when-to-use-dev-random-over-dev-urandom-in-linux) e.g. for the differences between `/dev/random` and `dev/urandom`. – Jakob Stark Mar 10 '22 at 09:18
There are pseudo random number generators (PRNG) of very different quality and typical usage. Typical characteristics of PRNGs are:
- The repeating period. This is the number of different numbers, that a PRNG can produce and for good generators this is almost always two to the power of the bitwidth.
- Hidden patterns. Some bad PRNGs have hidden patterns. Obviously they decrease the quality of the random numbers. There are tests, that can be used to quantify the quality in this regard. This property, as well as the speed are mainly important for scientific usage like monte carlo simulation.
- Cryptographic security. For cryptographic operations there is the need of special PRNGs with very specific use cases. You can reed more about them for example on wikipedia.
What I am trying to show you here, is that the choice of the right PRNG is just as important as the right choice of the seed. It turns out that the C rand()
performs very bad in all three of the above categories (with exception maybe of the speed). That means if you seed rand()
once and repeatedly call it and print say rand() % 11
, an attacker will be able to synchronize to the PRNG after a short period of time even if you used the most secure and random seed. The rand()
as well as most other, better random generators in the C++ standard library, were designed to be used for scientific calculations and are not suitable for cryptographic purposes.
If you need cryptographically secure random numbers I would suggest you to use a library that is build for exactly that purpose. A widely used crypto library, that can be used cross platform is OpenSSL. It includes a function called RAND_bytes()
that can be used for secure random numbers. Do not forget to carefully read the manual page if you want to use it. You have to check the return value for errors!

- 3,346
- 6
- 22