Mercurial > jwe > octave
changeset 28602:a61b651914d6
Use C++11 functions to gather entropy from system (bug #58800).
* randmtzig.cc (octave::init_mersenne_twister): Gather entropy for algorithm
from random_device if available. Use PID as additional entropy source.
author | Markus Mützel <markus.muetzel@gmx.de> |
---|---|
date | Thu, 23 Jul 2020 14:24:46 +0200 |
parents | b81238f3ecdb |
children | 43c285a20829 |
files | liboctave/numeric/randmtzig.cc |
diffstat | 1 files changed, 39 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/numeric/randmtzig.cc Sat Jul 25 11:33:55 2020 +0200 +++ b/liboctave/numeric/randmtzig.cc Thu Jul 23 14:24:46 2020 +0200 @@ -162,7 +162,9 @@ #include <cstdio> #include <algorithm> +#include <random> +#include "oct-syscalls.h" #include "oct-time.h" #include "randmtzig.h" @@ -259,36 +261,50 @@ uint32_t entropy[MT_N]; int n = 0; - /* Look for entropy in /dev/urandom */ - FILE *urandom = std::fopen ("/dev/urandom", "rb"); - if (urandom) - { - while (n < MT_N) - { - unsigned char word[4]; - if (std::fread (word, 4, 1, urandom) != 1) - break; - entropy[n++] = word[0] + (word[1]<<8) + (word[2]<<16) - + (static_cast<uint32_t> (word[3])<<24); - } - std::fclose (urandom); - } - - /* If there isn't enough entropy, gather some from various sources */ + // Gather some entropy from various sources sys::time now; + // Current time in seconds if (n < MT_N) - entropy[n++] = now.unix_time (); /* Current time in seconds */ + entropy[n++] = now.unix_time (); + + // CPU time used (usec) + if (n < MT_N) + entropy[n++] = clock (); + + // Fractional part of current time + if (n < MT_N) + entropy[n++] = now.usec (); + + // Include the PID to make sure that several processes reaching here at the + // same time use different random numbers. + if (n < MT_N) + entropy[n++] = sys::getpid (); if (n < MT_N) - entropy[n++] = clock (); /* CPU time used (usec) */ + { + try + { + // The standard doesn't *guarantee* that random_device provides + // non-deterministic random numbers. So add entropy from this + // source last to make sure we gathered at least some entropy from + // the earlier sources. + std::random_device rd; + std::uniform_int_distribution<uint32_t> dist; + // Add 1024 bit of "true" entropy + int n_max = std::min (n + 32, MT_N); + while (n < n_max) + entropy[n++] = dist (rd); + } + catch (std::exception& e) + { + // Just ignore any exception and skip that source of entropy. + } + } - if (n < MT_N) - entropy[n++] = now.usec (); /* Fractional part of current time */ - - /* Send all the entropy into the initial state vector */ - init_mersenne_twister (entropy,n); + // Send all the entropy into the initial state vector + init_mersenne_twister (entropy, n); } void set_mersenne_twister_state (const uint32_t *save)