1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 02:47:35 +00:00

LibCrypto: Fix random number generation

This commit is contained in:
Ben Wiederhake 2020-08-15 20:10:47 +02:00 committed by Andreas Kling
parent 2e470a4a47
commit d33e3b7d8a
2 changed files with 21 additions and 16 deletions

View file

@ -306,20 +306,25 @@ static bool MR_primality_test(UnsignedBigInteger n, const Vector<UnsignedBigInte
return true;
}
static UnsignedBigInteger random_number(const UnsignedBigInteger& min, const UnsignedBigInteger& max)
static UnsignedBigInteger random_number(const UnsignedBigInteger& min, const UnsignedBigInteger& max_excluded)
{
ASSERT(min < max);
auto range = max.minus(min);
ASSERT(min < max_excluded);
auto range = max_excluded.minus(min);
UnsignedBigInteger base;
auto size = range.trimmed_length() * sizeof(u32);
auto size = range.trimmed_length() * sizeof(u32) + 2;
// "+2" is intentional (see below).
u8 buf[size];
AK::fill_with_random(buf, size);
Vector<u32> vec;
for (size_t i = 0; i < size / sizeof(u32); ++i) {
vec.append(*(u32*)buf + i);
}
UnsignedBigInteger offset { move(vec) };
return offset.plus(min);
UnsignedBigInteger random { buf, size };
// At this point, `random` is a large number, in the range [0, 256^size).
// To get down to the actual range, we could just compute random % range.
// This introduces "modulo bias". However, since we added 2 to `size`,
// we know that the generated range is at least 65536 times as large as the
// required range! This means that the modulo bias is only 0.0015%, if all
// inputs are chosen adversarially. Let's hope this is good enough.
auto divmod = random.divided_by(range);
// The proper way to fix this is to restart if `divmod.quotient` is maximal.
return divmod.remainder.plus(min);
}
static bool is_probably_prime(const UnsignedBigInteger& p)