Skip to content

Commit 1d207bc

Browse files
committed
Add hash strengthening to the RNG
Once every minute, this will feed the RNG state through repeated SHA512 for 10ms. The timings of that operation are used as entropy source as well.
1 parent 94167e2 commit 1d207bc

File tree

1 file changed

+54
-4
lines changed

1 file changed

+54
-4
lines changed

src/random.cpp

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,34 @@ static bool GetHardwareRand(unsigned char* ent32) noexcept {
143143
return false;
144144
}
145145

146+
/** Use repeated SHA512 to strengthen the randomness in seed32, and feed into hasher. */
147+
static void Strengthen(const unsigned char (&seed)[32], int microseconds, CSHA512& hasher) noexcept
148+
{
149+
CSHA512 inner_hasher;
150+
inner_hasher.Write(seed, sizeof(seed));
151+
152+
// Hash loop
153+
unsigned char buffer[64];
154+
int64_t stop = GetTimeMicros() + microseconds;
155+
do {
156+
for (int i = 0; i < 1000; ++i) {
157+
inner_hasher.Finalize(buffer);
158+
inner_hasher.Reset();
159+
inner_hasher.Write(buffer, sizeof(buffer));
160+
}
161+
// Benchmark operation and feed it into outer hasher.
162+
int64_t perf = GetPerformanceCounter();
163+
hasher.Write((const unsigned char*)&perf, sizeof(perf));
164+
} while (GetTimeMicros() < stop);
165+
166+
// Produce output from inner state and feed it to outer hasher.
167+
inner_hasher.Finalize(buffer);
168+
hasher.Write(buffer, sizeof(buffer));
169+
// Try to clean up.
170+
inner_hasher.Reset();
171+
memory_cleanse(buffer, sizeof(buffer));
172+
}
173+
146174
static void RandAddSeedPerfmon(CSHA512& hasher)
147175
{
148176
#ifdef WIN32
@@ -436,7 +464,23 @@ static void SeedSlow(CSHA512& hasher) noexcept
436464
SeedTimestamp(hasher);
437465
}
438466

439-
static void SeedSleep(CSHA512& hasher)
467+
/** Extract entropy from rng, strengthen it, and feed it into hasher. */
468+
static void SeedStrengthen(CSHA512& hasher, RNGState& rng) noexcept
469+
{
470+
static std::atomic<int64_t> last_strengthen{0};
471+
int64_t last_time = last_strengthen.load();
472+
int64_t current_time = GetTimeMicros();
473+
if (current_time > last_time + 60000000) { // Only run once a minute
474+
// Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher.
475+
unsigned char strengthen_seed[32];
476+
rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false);
477+
// Strengthen it for 10ms (100ms on first run), and feed it into hasher.
478+
Strengthen(strengthen_seed, last_time == 0 ? 100000 : 10000, hasher);
479+
last_strengthen = current_time;
480+
}
481+
}
482+
483+
static void SeedSleep(CSHA512& hasher, RNGState& rng)
440484
{
441485
// Everything that the 'fast' seeder includes
442486
SeedFast(hasher);
@@ -452,9 +496,12 @@ static void SeedSleep(CSHA512& hasher)
452496

453497
// Windows performance monitor data (once every 10 minutes)
454498
RandAddSeedPerfmon(hasher);
499+
500+
// Strengthen every minute
501+
SeedStrengthen(hasher, rng);
455502
}
456503

457-
static void SeedStartup(CSHA512& hasher) noexcept
504+
static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
458505
{
459506
#ifdef WIN32
460507
RAND_screen();
@@ -465,6 +512,9 @@ static void SeedStartup(CSHA512& hasher) noexcept
465512

466513
// Windows performance monitor data.
467514
RandAddSeedPerfmon(hasher);
515+
516+
// Strengthen
517+
SeedStrengthen(hasher, rng);
468518
}
469519

470520
enum class RNGLevel {
@@ -489,15 +539,15 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
489539
SeedSlow(hasher);
490540
break;
491541
case RNGLevel::SLEEP:
492-
SeedSleep(hasher);
542+
SeedSleep(hasher, rng);
493543
break;
494544
}
495545

496546
// Combine with and update state
497547
if (!rng.MixExtract(out, num, std::move(hasher), false)) {
498548
// On the first invocation, also seed with SeedStartup().
499549
CSHA512 startup_hasher;
500-
SeedStartup(startup_hasher);
550+
SeedStartup(startup_hasher, rng);
501551
rng.MixExtract(out, num, std::move(startup_hasher), true);
502552
}
503553

0 commit comments

Comments
 (0)