From: Phil Carmody Date: Tue, 30 Jan 2018 16:48:51 +0000 (+0200) Subject: lib/randgen - use KISS as intended, not as originally posted to sci.crypt X-Git-Tag: 2.3.9~2398 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=605b1a5e462b39dff4c331133469c4eba0a7103a;p=thirdparty%2Fdovecot%2Fcore.git lib/randgen - use KISS as intended, not as originally posted to sci.crypt The original KISS, as posted to sci.crypt, had a SHR3 component with short cycles. The buggy version contradicted Marsaglia's original cycle length claim, and it had already been fixed in KISS11, so it's fair to assume this was always the intended implementation. For details see G. Rose "KISS: A Bit Too Simple". Whilst dealing with that issue, fix seeding so w and z can't both be short (length 2) cycles, as also pointed out in the Rose paper. Signed-off-by: Phil Carmody --- diff --git a/src/lib/randgen.c b/src/lib/randgen.c index d858c77c43..f5aaf36862 100644 --- a/src/lib/randgen.c +++ b/src/lib/randgen.c @@ -7,7 +7,8 @@ #ifdef DEBUG /* For reproducing tests, fall back onto using a simple deterministic PRNG */ -/* Marsaglia's 1999 KISS, de-macro-ified */ +/* Marsaglia's 1999 KISS, de-macro-ified, and with the fixed KISS11 SHR3, + which is clearly what was intended given the "cycle length 2^123" claim. */ static bool kiss_in_use; static unsigned int kiss_seed; static uint32_t kiss_z, kiss_w, kiss_jsr, kiss_jcong; @@ -17,7 +18,7 @@ kiss_init(unsigned int seed) /* i_info("Random numbers are PRNG using kiss, seeded with %u", seed); */ kiss_seed = seed; kiss_jsr = 0x5eed5eed; /* simply musn't be 0 */ - kiss_z = kiss_w = kiss_jcong = seed; + kiss_z = 1 ^ (kiss_w = kiss_jcong = seed); /* w=z=0 is bad, see Rose */ kiss_in_use = TRUE; } static unsigned int @@ -26,8 +27,8 @@ kiss_rand(void) kiss_z = 36969 * (kiss_z&65535) + (kiss_z>>16); kiss_w = 18000 * (kiss_w&65535) + (kiss_w>>16); kiss_jcong = 69069 * kiss_jcong + 1234567; - kiss_jsr^=(kiss_jsr<<17); - kiss_jsr^=(kiss_jsr>>13); + kiss_jsr^=(kiss_jsr<<13); /* <<17, >>13 gives cycle length 2^28.2 max */ + kiss_jsr^=(kiss_jsr>>17); /* <<13, >>17 gives maximal cycle length */ kiss_jsr^=(kiss_jsr<<5); return (((kiss_z<<16) + kiss_w) ^ kiss_jcong) + kiss_jsr; }