Post
Topic
Board Development & Technical Discussion
Merits 9 from 4 users
Re: Is it possible to generate an already existing seed?
by
nullius
on 30/01/2018, 22:42:14 UTC
⭐ Merited by hatshepsut93 (3) ,PoolMinor (2) ,pebwindkraft (2) ,ETFbitcoin (2)
An analogous situation is when a random number generator isn't sufficiently random - the crypto seeds it generates may be a small population.

Correct.  Private keys that are randomly chosen from the entire set of valid private keys are secure.  Private keys that are randomly chosen from a small definable subset of valid private keys can be VERY insecure.

This is why in my own post above, I specified, “with working random number generators”.  This is imperative for any cryptographic software of any kind; if you do not have a working CSPRNG, where the CS stands for Cryptographically Secure, then you have nothing else, either.

The lack of randomness may have insidious causes, for example seeding the RNG with the microsecond timestamp of a keypress. But it may turn out that USB is polled at a rate derived from the same microsecond clock. You may think the timestamp has 10 bits of entropy, but it really only has 3. This may seem to generate unique seeds, but alas, they're not good enough.

Which is why it is generally a bad idea to try to reinvent cryptography on your own without a SIGNIFICANT amount of education, study, and expertise.  When it comes to maths and physics, what "feels intuitive" to someone that has a limited knowledge can often be COMPLETELY WRONG.

In my preferred kernel (FreeBSD), as of last time I read those portions of the code, the entropy harvester does not feed the PRNG an estimate of more than 1–2 bits of entropy for any hardware event.  I am of the school of thought that entropy estimation as a concept is problematic at best; but if and when it must be done, it must be done conservatively.

Estimating 10 bits of entropy off a single instance of any microsecond timer event seems suicidal to me.  Among other problems, this translates to an assumption that all precision below one millisecond in the timing of that event be completely unpredictable in all circumstances—even to unprivileged code running on the same CPU as handles the interrupt!

DannyHamilton is right:  The acquisition of cryptographically secure randomness is not only an expert domain, but a specialist expert domain which invokes both maths and physics.  Even professional mathematicians who are not cryptographers will probably get this wrong.  Almost all working programmers will get it wrong.  Once upon a time, the individual entrusted to maintain Debian’s vendored OpenSSL got it very, very wrong—causing a spectacular blow-up of most cryptography involving Debian systems from 2006–08.  Conventional wisdom gets an awful lot wrong.  There is a high probability (hah!) that you will get it wrong, too.

Worst of all, there is no certain means to prove that you got it right.  Statistical tests can easily demonstrate that a given bag of bits is not random; but no test can prove that one is.  Passing the DieHard suite (or similar) does not mean that your numbers are sufficiently random for cryptographic purposes.  The only way to be sure is to possess a deep theoretical knowledge matched by practical knowledge of real-world cryptanalytic attacks which target insufficiency of entropy.


Don’t take any chances with your randomness!

On Unix or Linux, read() off /dev/urandom; or use whatever special nonportable APIs may be offered to obtain randomness directly from the kernel (getrandom(), a special sysctl, etc.).  On other platforms, find the equivalent.  If writing a web application, use getRandomValues() (for most any current browser) or, if feasible, the generateKey method; then, pray to whatever gods you believe in that the browser is not too stupid.


Do not roll your own.  Do not conflate distinct meanings of the overloaded word “entropy”, then gather “entropy” the same measurements as taken by Panopticlick (!) (!!) (for Bitcoin!).  Also, do not roll your own using C’s rand(), e.g.:

Quote
Code:
/* true_random -- generate a crypto-quality random number. */
static int true_random(void)
{
    /* crap. this isn't crypto quality, but it will be Good Enough */
    srand((unsigned int)(((time_now >> 32) ^ time_now) & 0xffffffff));

    return rand() & 0x0FFFF;
}

Let that horror be a lesson.  For unless you have considerable specialist expertise, you cannot rely on your results being any better.  And I repeat:  If you do not have a working Cryptographically Secure PRNG, then you have nothing else, either.