Of the use of unpredictableSeed

cym13 via Digitalmars-d digitalmars-d at puremagic.com
Sun Feb 26 16:10:31 PST 2017


On Sunday, 26 February 2017 at 22:56:14 UTC, Nick Sabalausky 
(Abscissa) wrote:
> On 02/26/2017 01:23 PM, cym13 wrote:
>> Hi,
>>
>> I found many times that people use unpredictableSeed in 
>> combination with
>> normal PRNG for cryptographic purpose. Some even go as far as 
>> reseeding
>> at each call to try making it more secure.
>>
>> It is a dangerous practice, most PRNG are not designed with 
>> security
>> (and unpredictability) in mind, and unpredictableSeed was 
>> definitely not
>> designed with security in mind (or it failed heavily at it). 
>> It's a good
>> tool when one needs randomness, not security.
>>
>> I wrote a blog post to present exactly why this is a bad idea 
>> and how it
>> could be exploited [1].
>>
>> The best would be to add a standard CSPRNG interface to Phobos 
>> but we
>> aren't there yet.
>>
>> [1]: https://cym13.github.io/article/unpredictableSeed.html
>
> FWIW, DAuth[1] uses, and offers, an implementation of 
> Hash_DRBG, a well-known and established CSPRNG algorithm. It's 
> entropy source (not exactly the same as a seed, but basically 
> the CSPRNG equivalent) is customizable, but by default, it uses 
> _RtlGenRandom on Windows (the same source used by the 
> CryptGenRandom algorithms) and '/dev/urandom' on Posix:
>
> https://github.com/Abscissa/DAuth/blob/master/src/dauth/hashdrbg.d
>
> [1] Ugh, still haven't gotten around to finishing DAuth's new 
> version, renamed "InstaUser".

And it is very interesting to note that you fall into the very 
exact problem I am describing in my post if it weren't that your 
default PRNG isn't seedable. Use any other PRNG and you are 
vulnerable (if I read it correctly, I haven't spent much time on 
that).

 From random.d, the function randomToken calls randomBytes which 
inits a new PRNG which is seeded with unpredictableSeed which 
becomes the actual PRNG used:

string randomToken(Rand = DefaultCryptoRand)(size_t strength = 
defaultTokenStrength)
	if(isDAuthRandom!Rand)
{
	return TokenBase64.encode( randomBytes!Rand(strength) );
}

ubyte[] randomBytes(Rand = DefaultCryptoRand)(size_t numBytes)
	if(isDAuthRandom!Rand)
{
	Rand rand;
	rand.initRand();
	return randomBytes(numBytes, rand);
}

private void initRand(Rand)(ref Rand rand)
	if(isDAuthRandom!Rand)
{
	static if(isSeedable!Rand)
		rand.seed(unpredictableSeed);
}

The only thing that saves you here is that your DefaultCryptoRand 
isn't seedable. Note that I'm not saying that to bash you or 
anything, it just happens to show well why I think my article was 
necessary.


More information about the Digitalmars-d mailing list