mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-18 13:17:55 +02:00
Merge 82b64a5a81 into merged_master (Bitcoin PR #15224)
This commit is contained in:
commit
6d8012ae9b
2 changed files with 56 additions and 4 deletions
|
|
@ -237,6 +237,34 @@ static void SeedHardwareSlow(CSHA512& hasher) noexcept {
|
|||
#endif
|
||||
}
|
||||
|
||||
/** Use repeated SHA512 to strengthen the randomness in seed32, and feed into hasher. */
|
||||
static void Strengthen(const unsigned char (&seed)[32], int microseconds, CSHA512& hasher) noexcept
|
||||
{
|
||||
CSHA512 inner_hasher;
|
||||
inner_hasher.Write(seed, sizeof(seed));
|
||||
|
||||
// Hash loop
|
||||
unsigned char buffer[64];
|
||||
int64_t stop = GetTimeMicros() + microseconds;
|
||||
do {
|
||||
for (int i = 0; i < 1000; ++i) {
|
||||
inner_hasher.Finalize(buffer);
|
||||
inner_hasher.Reset();
|
||||
inner_hasher.Write(buffer, sizeof(buffer));
|
||||
}
|
||||
// Benchmark operation and feed it into outer hasher.
|
||||
int64_t perf = GetPerformanceCounter();
|
||||
hasher.Write((const unsigned char*)&perf, sizeof(perf));
|
||||
} while (GetTimeMicros() < stop);
|
||||
|
||||
// Produce output from inner state and feed it to outer hasher.
|
||||
inner_hasher.Finalize(buffer);
|
||||
hasher.Write(buffer, sizeof(buffer));
|
||||
// Try to clean up.
|
||||
inner_hasher.Reset();
|
||||
memory_cleanse(buffer, sizeof(buffer));
|
||||
}
|
||||
|
||||
static void RandAddSeedPerfmon(CSHA512& hasher)
|
||||
{
|
||||
#ifdef WIN32
|
||||
|
|
@ -529,7 +557,23 @@ static void SeedSlow(CSHA512& hasher) noexcept
|
|||
SeedTimestamp(hasher);
|
||||
}
|
||||
|
||||
static void SeedSleep(CSHA512& hasher)
|
||||
/** Extract entropy from rng, strengthen it, and feed it into hasher. */
|
||||
static void SeedStrengthen(CSHA512& hasher, RNGState& rng) noexcept
|
||||
{
|
||||
static std::atomic<int64_t> last_strengthen{0};
|
||||
int64_t last_time = last_strengthen.load();
|
||||
int64_t current_time = GetTimeMicros();
|
||||
if (current_time > last_time + 60000000) { // Only run once a minute
|
||||
// Generate 32 bytes of entropy from the RNG, and a copy of the entropy already in hasher.
|
||||
unsigned char strengthen_seed[32];
|
||||
rng.MixExtract(strengthen_seed, sizeof(strengthen_seed), CSHA512(hasher), false);
|
||||
// Strengthen it for 10ms (100ms on first run), and feed it into hasher.
|
||||
Strengthen(strengthen_seed, last_time == 0 ? 100000 : 10000, hasher);
|
||||
last_strengthen = current_time;
|
||||
}
|
||||
}
|
||||
|
||||
static void SeedSleep(CSHA512& hasher, RNGState& rng)
|
||||
{
|
||||
// Everything that the 'fast' seeder includes
|
||||
SeedFast(hasher);
|
||||
|
|
@ -545,9 +589,12 @@ static void SeedSleep(CSHA512& hasher)
|
|||
|
||||
// Windows performance monitor data (once every 10 minutes)
|
||||
RandAddSeedPerfmon(hasher);
|
||||
|
||||
// Strengthen every minute
|
||||
SeedStrengthen(hasher, rng);
|
||||
}
|
||||
|
||||
static void SeedStartup(CSHA512& hasher) noexcept
|
||||
static void SeedStartup(CSHA512& hasher, RNGState& rng) noexcept
|
||||
{
|
||||
#ifdef WIN32
|
||||
RAND_screen();
|
||||
|
|
@ -561,6 +608,9 @@ static void SeedStartup(CSHA512& hasher) noexcept
|
|||
|
||||
// Windows performance monitor data.
|
||||
RandAddSeedPerfmon(hasher);
|
||||
|
||||
// Strengthen
|
||||
SeedStrengthen(hasher, rng);
|
||||
}
|
||||
|
||||
enum class RNGLevel {
|
||||
|
|
@ -585,7 +635,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
|
|||
SeedSlow(hasher);
|
||||
break;
|
||||
case RNGLevel::SLEEP:
|
||||
SeedSleep(hasher);
|
||||
SeedSleep(hasher, rng);
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -593,7 +643,7 @@ static void ProcRand(unsigned char* out, int num, RNGLevel level)
|
|||
if (!rng.MixExtract(out, num, std::move(hasher), false)) {
|
||||
// On the first invocation, also seed with SeedStartup().
|
||||
CSHA512 startup_hasher;
|
||||
SeedStartup(startup_hasher);
|
||||
SeedStartup(startup_hasher, rng);
|
||||
rng.MixExtract(out, num, std::move(startup_hasher), true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
* - RandAddSeedSleep() seeds everything that fast seeding includes, but additionally:
|
||||
* - A high-precision timestamp before and after sleeping 1ms.
|
||||
* - (On Windows) Once every 10 minutes, performance monitoring data from the OS.
|
||||
- - Once every minute, strengthen the entropy for 10 ms using repeated SHA512.
|
||||
* These just exploit the fact the system is idle to improve the quality of the RNG
|
||||
* slightly.
|
||||
*
|
||||
|
|
@ -51,6 +52,7 @@
|
|||
* - 256 bits from the hardware RNG (rdseed or rdrand) when available.
|
||||
* - (On Windows) Performance monitoring data from the OS.
|
||||
* - (On Windows) Through OpenSSL, the screen contents.
|
||||
* - Strengthen the entropy for 100 ms using repeated SHA512.
|
||||
*
|
||||
* When mixing in new entropy, H = SHA512(entropy || old_rng_state) is computed, and
|
||||
* (up to) the first 32 bytes of H are produced as output, while the last 32 bytes
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue