I want to produce a random cryptographic key on Windows. Where can I obtain entropy?
I would like my entropy function to work without a network connection and to be reliable on Windows 2000 and upwards. Even sources which may or may not provide a small amount of entropy could be useful as all the sources will be pooled.
This is my initial list of functions:
GetCurrentProcessID,
GetCurrentThreadID,
GetTickCount,
GetLocalTime,
QueryPerformanceCounter,
GlobalMemoryStatus,
GetDiskFreeSpace,
GetComputerName,
GetUserName,
GetCursorPos,
GetMessageTime,
GetSystemInfo,
CryptGenRandom,
GetProcessHandleCount,
GetProcessMemoryInfo.
Although early versions of the CryptGenRandom function may contain weaknesses later versions follow secure standards (see remarks on the CrypGenRandom page.)
It is weak to just use time as your seed. There is an answer under What is the most secure seed for random number generation? which explains that the unpredictable random seed may only need 128 bits to produce a secure PRNG. It is therefore probably unnecessary to find more sources than those listed in the question, and normally the CryptGenRandom function will already contain and generate enough entropy for itself that the caller does not need to do any of this.
CryptGenRandom and the function CryptAcquireContext which must preceed it can be called from Delphi like this.
If its an option you can ask user to move mouse pointer for a while.
The only external source that most machines have is Mic In/Line In, call waveInOpen+waveInPrepareHeader+waveInAddBuffer+waveInStart. How random that is probably depends on the hardware...
Related
I don't know much about RISCV (actually thinking about Open RISC) and what little I have read tells it is about creating and optimizing things. Now people (FSF for instance) has suspected time and again that security forces may be giving weak random number generators and whatever passwords are generated could be broken by them easily.
While I don't know whether to believe that or not, from what little I read, it seemed RISC might be a platform which may make and have lot of improvements in random number generator (creation and secrecy both). Is this true or just fanciful thoughts ?
RISC-V and OpenRISC are Instruction Set Architectures (ISA) and have nothing to do with random number generators. Although an ISA can have dedicated instructions for generating random numbers.
Everything that is security related can be attacked in different ways like side channel attacks or timing attacks. Those attacks depend on the hardware and software implementations and not on the ISA.
We need to migrate to a better RNG or RBG for some key value generation which will be further used for encryption of the data.
Which will be the most suitable algorithm? Shall I consider NIST doc for this?
Any pseudo random number generator that produces a Gaussian distribution and that has a wide output (say at least 32 bits) should be enough for creating keys. It's up to you to determine your needs and then find a matching RNG.
For more info, see http://www.random.org/randomness.
Depending on the language you choose to implement this, I'm sure you can find source code for pseudo-RNG on the Web, if the one built-in into your system isn't good enough.
As we are a programming site, I would seriously look at the secure random number generators at your disposal in your particular runtime environment. In general you will have to rely on system resources to generate randoms, at least to seed the pseudo random number generator. The only possible exception are CPU specific random instructions, such as the ones used on the latest Intel CPU's (hopefully well-tested secure RNGs will become a main feature of CPU's).
Within many programming environments there is very little choice but to use OpenSSL or /dev/random for seeding. In general it is hard to find useful information about the random number generator. Sometimes the RNG is really not suitable at all (e.g. the native PHP version).
If possible, try to find something that conforms to NIST requirements.
I am looking for an equivalent to drand48 on Windows. To all who do not know, the following is not equivalent:
(double)rand()/RAND_MAX;
Firstly, rand returns values including RAND_MAX
Secondly, on Windows RAND_MAX=32767 which is a too short period for my application.
My purpose is to generate noise for a simulation. It is desirable to use a pseudo-random generator with the same period as drand48.
Firstly, note that you appear to be confusing the resolution with the period. On Windows, rand will return values from 0 to 32767, but this does not mean that the same values will repeat every 32768 calls. So rand should be perfectly adequate unless you need more than 16 bits of resolution. (The resolution and the period are the same in drand48, but not in all pseudorandom number generators.)
If you do not need the exact behaviour of drand48, rand_s would be the simplest option. It has a 32-bit resolution, less than drand48 but enough for most purposes. It generates a cryptographically secure random number, so there is no fixed period. One possible issue is that it will be much slower than drand48.
If you want the same behaviour of drand48, the algorithm is documented and should be easy to re-implement, or you could use the source code from FreeBSD (link to source code browser on http://fxr.watson.org/).
7 years late to the party. Sorry.
Gnu Scientific Library is a good solution to this problem. The library employs several high-quality generating algorithms.
https://www.gnu.org/software/gsl/doc/html/rng.html
It might not be an exact answer to your question, but still it is a solution. Use the CryptGenRandom(it's form the WinAPI).
Let us assume we're generating very large (e.g. 128 or 256bit) numbers to serve as keys for a block cipher.
Let us further assume that we wear tinfoil hats (at least when outside).
Being so paranoid, we want to be sure of our available entropy, but we don't entirely trust any particular source. Maybe the government is rigging our coins. Maybe these dice are ever so subtly weighted. What if the hardware interrupts feeding into /dev/random are just a little too consistent? (Besides being paranoid, we're lazy enough that we don't want to generate it all by hand...)
So, let's mix them all up.
What are the secure method(s) for doing this? Presumably just concatenating a few bytes from each source isn't entirely secure -- if one of the sources is biased, it might, in theory, lend itself to such things as a related-key attack, for example.
Is running SHA-256 over the concatenated bytes sufficient?
(And yes, at some point soon I am going to pick up a copy of Cryptography Engineering. :))
Since you mention /dev/random -- on Linux at least, /dev/random is fed by an algorithm that does very much what you're describing. It takes several variously-trusted entropy sources and mixes them into an "entropy pool" using a polynomial function -- for each new byte of entropy that comes in, it's xor'd into the pool, and then the entire pool is stirred with the mixing function. When it's desired to get some randomness out of the pool, the entire pool is hashed with SHA-1 to get the output, then the pool is mixed again (and actually there's some more hashing, folding, and mutilating going on to make sure that reversing the process is about as hard as reversing SHA-1). At the same time, there's a bunch of accounting going on -- each time some entropy is added to the pool, an estimate of the number of bits of entropy it's worth is added to the account, and each time some bytes are extracted from the pool, that number is subtracted, and the random device will block (waiting on more external entropy) if the account would go below zero. Of course, if you use the "urandom" device, the blocking doesn't happen and the pool simply keeps getting hashed and mixed to produce more bytes, which turns it into a PRNG instead of an RNG.
Anyway... it's actually pretty interesting and pretty well commented -- you might want to study it. drivers/char/random.c in the linux-2.6 tree.
Using a hash function is a good approach - just make sure you underestimate the amount of entropy each source contributes, so that if you are right about one or more of them being less than totally random, you haven't weakened your key unduly.
This isn't dissimilar to the approach used in key stretching (though you have no need for multiple iterations here).
I've done this before, and my approach was just to XOR them, byte-by-byte, against each other.
Running them through some other algorithm, like SHA-256, is terribly inefficient, so it's not practical, and I think it would be not really useful and possibly harmful.
If you do happen to be incredibly paranoid, and have a tiny bit of money, it might be fun to buy a "true" (depending on how convinced you are by Quantum Mechanics) a Quantum Random Number Generator.
-- Edit:
FWIW, I think the method I describe above (or something similar) is effectively a One-Time Pad from the point of view of either sources, assuming one of them is random, and therefore unattackable assuming they are independant and out to get you. I'm happy to be corrected on this if someone takes issue with it, and I encourage anyone not taking issue with it to question it anyway, and find out for yourself.
If you have a source of randomness but you're not sure whether it is biased or not, then there are a lot of different algorithms. Depending on how much work you want to do, the entropy you waste from the original source differes.
The easiest algorithm is the (improved) van Neumann algorithm. You can find the details in this pdf:
http://security1.win.tue.nl/~bskoric/physsec/files/PhysSec_LectureNotes.pdf
at page 27.
I also recommend you to read this document if you're interested in how to produce uniformly randomness from a given souce, how true random number generators work, etc!
Currently, Boost only implements the random_device class for Linux (maybe *nix) systems. Does anyone know of existing implementations for other OS-es? Ideally, these implementations would be open-source.
If none exist, how should I go about implementing a non-deterministic RNG for Windows as well as Mac OS X? Do API calls exist in either environment that would provide this functionality? Thanks (and sorry for all the questions)!
On MacOSX, you can use /dev/random (since it's a *nix).
On Windows, you probably want the CryptGenRandom function. I don't know if there's an implementation of boost::random_device that uses it.
Depends on what you want to use you RNG for.
In general terms, you'll feed seed data into a buffer, generate hash values of the buffer, mix a counter into the result and hash it some more. The reason for using a hash function is that good hashes are designed to yield random-looking results from input data that's more structured.
If you want to use it for cryptography, things'll turn a lot hairier. You'll need to jump through more hoops to ensure that your RNG keeps repeating patterns within reasonably safe limits. I can recommend Bruce Schneier's "Practical Cryptography" (for an introduction on RNGs, and a sample implementation). He's also got some RNG-related stuff up about his yarrow RNG.
If boost relies on /dev/random, chances are it works on MacOS also (as it has that).
On Windows there is CryptoAPI as part of the OS, and that provides a crypto quality RNG.
Also, I believe modern Intel CPUs have a hardware RNG on the chip - however you'd have to figure out how to get at that on each OS. Using the higher level APIs is probably a better bet.
edit: Here's a link to how the Intel RNG works
OpenSSL has a decent one.
#include <openssl/rand.h>
...
time_t now = time(NULL);
RAND_seed(&now, sizeof(now)); // before first number you need
int success = RAND_bytes(...);
if (!success) die_loudly();
RAND_cleanup(); // after you don't need any more numbers
Microsoft CryptoAPI has one on Win32. It requires a few more function calls. Not including the details here because there are 2 to 5 args to each of these calls. Be careful, CryptoAPI seems to require the user to have a complete local profile (C:\Documents and Settings\user\Local Settings) correctly set up before it can give you a random number.
CryptAcquireContext // see docs
CryptGenRandom
CryptReleaseContext