OpenSSL get deterministic random keys - c++

For the sake of ease of deployment of a prototype of a distributed application I want to generate a list of openSSL keys that are deterministic based on some random seed.
I do already know that using srand(seed) does not work because openSSL uses a different soruce of randomness. I've checked out RAND_pseudo_bytes, but it seems to be using the same random source as the non-pseudo method so that one doesn't seem to be doing it either.
Is there a way to generate the SSL keys deterministically?

Related

Is srand a reliable source of encryption pads?

I'm looking to encrypt license keys on an audio software plugin. The biggest risk to the integrity of the license keys is small-time crackers decompiling the code and looking for the encryption key. My solution is to store an arbitrary number in the code and feed it to an algorithm that will obfuscate the encryption key while still allowing me to differ the key between projects (I'm a freelancer).
My question is - will seeding the C++ random number generator create the same psuedo-random encryption key every time, or will it differ between runs, libraries, etcetera. It's fine if it differs between operating systems, I just need it to not differ between SDKs and hosting softwares on the same computer.
srand and rand will produce the same sequence of numbers when you use the same implementation. Change compilers, even to a newer version of the same compiler, and there are no guarantees,
But the new random number generators, introduced in C++11 and defined in <random>, are requires to generate the same sequence of numbers on all implementations.

Cryptographically secure RNG in C++ for RSA PKCS#1 (key generation)

I'm trying to re-implement the RSA key generation in C++ (as a hobby/learning playground) and by far my biggest problem seems to be generating a random number in range x,y which is also cryptographically secure (the primes p and q, for example).
I suppose using mt19937 or std::rand with a secure random seed (e.g. /dev/urandom or OpenSSL RAND_bytes etc) would not be considered 'cryptographically secure' in this case (RSA)?
ISAAC looked promising but I have zero clue on how to use it since I wasn't able to find any documentation at all.
Notably, this is also my first C++ project (I've done some C, Rust etc before... So C++ at least feels somewhat familiar and I'm not a complete newbie, mind you).
I suppose using mt19937 or std::rand with a secure random seed (e.g. /dev/urandom or OpenSSL RAND_bytes etc) would not be considered 'cryptographically secure' in this case (RSA)?
No, those are not cryptographically secure for basically any purpose.
ISAAC looked promising but I have zero clue on how to use it since I wasn't able to find any documentation at all.
Well, it stood the time I suppose. But I'd simply use a C++ library such as Crypto++ or Botan or something similar and then just implement the RSA key pair generation bit, borrowing one of their secure random generators. With a bit of luck they also have a bignum library so that you don't have to implement that either.

Is std::random_device cryptographic secure?

I see many people talk about security and std::random_device together.
For example, here slide 22.
According to cppreference, std::random_device :
std::random_device is a uniformly-distributed integer random number generator that produces non-deterministic random numbers.
It does not talk about security explicitly.
Is there any valid reference that explicitly mentions std::random_device is secure for cryptography?
No, because that's not what std::random_device is designed for; it's designed to generate random numbers, not to be secure.
In the context of security, randomness is something that is useful for key generation, but randomness is not something that is absolutely needed. For example, AES does not use any randomness, yet AES-256 is what is used to encrypt top secret information in the US.
One area where randomness and security cross, is when a random key is generated and used; if I can guess the seed and know the random protocol used, there's a good chance I can then use that same seed value to generate the same "random" value and thus the same key.
std::random_device will use a hardware module (like a hardware TPM) if one is available, otherwise it will use whatever the OS has as a RNG (like CryptGenRandom in Windows, or /dev/random in *nix systems), which might even be a PRNG (pseudo-random number generator), which might generate the same number depending on the random number algorithm used. As a side note: much like how the AES instruction set was incorporated into chipsets to speed up encryption and decryption, hardware RNG's help to give a larger entropy pool and faster random number generation as the algorithms are moved into hardware.
So if you are using std::random_device in any sort of cryptographic key generation, you'll need to be aware what random number generator is being used on the system being deployed to, otherwise you can have collisions and thus your encrypted system can be susceptible to duplicate key types of attack.
Hope that can help.
TL;DR: only use std::random_device to generate seeds for the defined PRNG's within this library. Otherwise use a cryptographic library such as Crypto++, Bothan, OpenSSL etc. to generate secure random numbers.
To have an idea why std::random_device is required it is important to see it in the light of the context for which it was defined.
std::random_device is part of a set of classes and methods that are used to generate deterministic/pseudo random number sequences fast. One example - also shown in the slides - is the Mersenne twister algorithm, which is certainly not cryptographically secure.
Now this is all very nice, but as the defined algorithms are all deterministic, this is arguably not what the users may be after: they want a fast random number generator that doesn't produce the same stream all of the time. Some kind of entropy source is required to seed the insecure PRNG. This is where std::random_device comes into action, it is used to seed the Mersenne twister (as shown in the slides referred to in the answer).
The slides show a speed difference of about 250 times for the Mersenne twister and the slow system provided non-deterministic random number generator. This clearly demonstrates why local, deterministic PRNG's can help to speed up random number generation.
Also note that local PRNG's won't slow down much when used from multiple threads. The system generator could be speedy when accessed by multiple threads, but this is certainly not a given. Sometimes system RNG's may even block or have latency or related issues.
As mentioned in the comments below the question, the contract for std::random_device is rather weak. It talks about using a "deterministic" generator if a system generator is not avialable. Of course, on most desktop / server configurations such a device (e.g. /dev/random or the non-blocking /dev/urandom device) is available. In that case std:random_device is rather likely to return a secure random number generator. However, you cannot rely on this to happen on all system configurations.
If you require a relatively fast secure random number generator I would recommend you use a cryptographic library such as OpenSSL or Crypto++ instead of using an insecure fast one the relatively slow system random generator. OpenSSL - for instance - will use the system random generator (as well as other entropy sources) to seed a more secure algorithm.

Can C++11 PRNG be used to produce repeatable results?

I'm working on a test suite for my package, and as part of the tests I would like to run my algorithm on a block of data. However, it occured to me that instead of hardcoding a particular block of data, I could use an algorithm to generate it. I'm wondering if the C++11 <random> facilities would be appropriate for this purpose.
From what I understand, the C++11 random number engines are required to implement specific algorithms. Therefore, given the same seed they should produce the same sequence of random integers in the range defined by the algorithm parameters.
However, as far as distributions are concerned, the standard specifies that:
The algorithms for producing each of the specified distributions are implementation-defined.
(26.5.8.1 Random number distribution class templates / In general)
Which — unless I'm mistaken — means that the output of a distribution is pretty much undefined. And from what I've tested, the distributions in GNU libstdc++ and LLVM project's libc++ produce different results given the same random engines.
The question would therefore be: what would be the most correct way of producing pseudo-random data that would be completely repeatable across different platforms?
what would be the most correct way of producing pseudo-random data that would be completely repeatable across different platforms?
That would be obvious: write your own distribution. As you yourself pointed out, the engines are cross-platform since they implement a specific algorithm. It's the distributions that are implementation-defined.
So write the distributions yourself.
Please see this answer: https://stackoverflow.com/a/34962942/1151329
I had exactly this problem and writing my own distributions worked perfectly. I got the same sequences across linux, OSx, windows, x86 and ARM.

How to ensure uniqe seeds for the RNG on subsequent process launches?

Summary: I need a simple self-contained way to seed my RNG so that the seed is different every time the program is launched.
Details:
I often need to run the same program (which does calculations with random numbers, e.g. Monte Carlo simulation etc.) many times to have good statistics on the result. In this case it is important that the random number generator will have a different seed on each run.
I would like to have a simple, cross-platform solution for this that can be contained within the program itself. (I.e. I don't want to always go to the trouble of having a script that launches each instance of the program with a different seed parameter.)
Note that using time(0) as a seed is not a good solution because the timer resolution is bad: if several processes are launched in parallel, they are likely to get the same seed from time(0).
Requirements:
as simple as possible
cross platform (currently I need it to work on Windows & Linux, x86 & x64 only).
self contained: shouldn't rely on a special way of launching the program (passing the seed as a parameter from the launch script is too much trouble).
I'd like to wrap the whole thing into a small library that I can include in any new project with minimal effort and just do something like SeedMyRNG(getSeed());
EDIT:
Although my main question was about doing this in C (or C++), based on the pointers provided in the answer I found os.urandom() as a Python solution (which is also useful for me).
Related relevant question: How to use /dev/random or urandom in C?
"Cross-platform" is a subjective term. Do you mean "any platform" (you might encounter in the future) or "every platform" (on your list of supported platforms)? Here's a pragmatic approach that I usually take:
Check if you have /dev/urandom; if yes, seed from there.
On Windows, use CryptGenRandom().
If all else fails, seed from time().
You could use dev random on Linux and the crypto api on Windows. Write a small library to present a platform independent interface and it should do exactly what you want.
Check out RandomLib
which is a C++ random number library with good support for seeds. In
particular
Random r;
r.Reseed();
causes r to be seeded with a vector of numbers (from a call to
RandomSeed::SeedVector()) which is almost certainly unique. This
includes the time, microseconds, pid, hostid, year.
Less optimally, you can also seed with RandomSeed::SeedWord() which
reads from /dev/urandom if possible. However, you will typically get a
seed collision after 2^16 runs with a single 32-bit word as your seed.
So, if your application is run many times, you are better off using the
bigger seed space offered by a vector.
Of course, this supposes that you are using a random number generator
that can make use of a vector seed. RandomLib offers MT19937 and
SFMT19937, which both use vector seeds.
Update on 2014-08-04:
Boost has a cross-platform implementation now, random_device. Here's an example for seeding a pseudo-random generator from boost using an unpredictable seed:
#include <boost/random/mersenne_twister.hpp>
#include <boost/random/random_device.hpp>
boost::random::mt11213b rng( (boost::random_device())() );