From 5464c961865e049279dc696a93fbaf08b8bc39ce Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 11 Nov 2020 14:44:35 +0100 Subject: [PATCH] random-util: add random_u64_range() that acquires a random number from a certain range, unbiased So far we have been quite sloppy with this and ignored modulus and range bias. Let's do something about, and add the option to do better. --- src/basic/random-util.c | 19 +++++++++++++++++++ src/basic/random-util.h | 2 ++ 2 files changed, 21 insertions(+) diff --git a/src/basic/random-util.c b/src/basic/random-util.c index c831f06dac..eca8187571 100644 --- a/src/basic/random-util.c +++ b/src/basic/random-util.c @@ -494,3 +494,22 @@ int random_write_entropy(int fd, const void *seed, size_t size, bool credit) { return 1; } + +int random_u64_range(uint64_t m) { + uint64_t x, remainder; + + /* Generates a random number in the range 0…m-1, unbiased. (Java's algorithm) */ + + if (m == 0) /* Let's take m == 0 as special case to return an integer from the full range */ + return random_u64(); + if (m == 1) + return 0; + + remainder = UINT64_MAX % m; + + do { + x = random_u64(); + } while (x >= UINT64_MAX - remainder); + + return x % m; +} diff --git a/src/basic/random-util.h b/src/basic/random-util.h index f661fc093a..1d5fb60fa2 100644 --- a/src/basic/random-util.h +++ b/src/basic/random-util.h @@ -40,3 +40,5 @@ int rdrand(unsigned long *ret); size_t random_pool_size(void); int random_write_entropy(int fd, const void *seed, size_t size, bool credit); + +int random_u64_range(uint64_t max);