[Python-ideas] PEP 504: Using the system RNG by default
Tim Peters
tim.peters at gmail.com
Wed Sep 16 21:13:27 CEST 2015
[Steven D'Aprano <steve at pearwood.info>, on "secrets"]
+1 on everything. Glad _that's_ finally over ;-)
One tech point:
> ...
> + secrets.random calls the CSPRNG; it just returns a random number
> (integer?). There is no API for getting or setting the state,
> setting the seed, or returning values from non-uniform
> distributions;
The OpenBSD arc4random() has a very sparse API, but gets this part
exactly right:
uint32_t arc4random_uniform(uint32_t upper_bound);
arc4random_uniform() will return a single 32-bit value, uniformly
distributed but less than upper_bound. This is recommended
over constructions like “arc4random() % upper_bound” as it
avoids "modulo bias" when the upper bound is not a power
of two. In the worst case, this function may consume multiple
iterations to ensure uniformity; see the source code to understand
the problem and solution.
In Python, there's no point to the uint32_t restrictions, and the
function is already implemented for arbitrary bigints via the current
(but private)
Random._randbelow() method, whose implementation could be simplified
for this specific use.
That in turn relies on the .getrandbits(number_of_bits) method, which
SystemRandom overrides.
So getrandbits() is the fundamental primitive. and SystemRandom
already implements that based on .urandom() results.
An OpenBSD-ish random_uniform(upper_bound) would be a "nice to have",
but not essential.
> + secrets.choice similarly uses the CSPRNG.
Apart from error checking, that's just:
def choice(seq):
return seq[self.random_uniform(len(seq))]
random.Random already does that (and SystemRandom inherits it),
although spelled with _randbelow().
More information about the Python-ideas
mailing list