mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 02:27:43 +00:00
LibCrypto: Fix random number generation
This commit is contained in:
parent
2e470a4a47
commit
d33e3b7d8a
2 changed files with 21 additions and 16 deletions
|
@ -306,20 +306,25 @@ static bool MR_primality_test(UnsignedBigInteger n, const Vector<UnsignedBigInte
|
||||||
return true;
|
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);
|
ASSERT(min < max_excluded);
|
||||||
auto range = max.minus(min);
|
auto range = max_excluded.minus(min);
|
||||||
UnsignedBigInteger base;
|
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];
|
u8 buf[size];
|
||||||
AK::fill_with_random(buf, size);
|
AK::fill_with_random(buf, size);
|
||||||
Vector<u32> vec;
|
UnsignedBigInteger random { buf, size };
|
||||||
for (size_t i = 0; i < size / sizeof(u32); ++i) {
|
// At this point, `random` is a large number, in the range [0, 256^size).
|
||||||
vec.append(*(u32*)buf + i);
|
// To get down to the actual range, we could just compute random % range.
|
||||||
}
|
// This introduces "modulo bias". However, since we added 2 to `size`,
|
||||||
UnsignedBigInteger offset { move(vec) };
|
// we know that the generated range is at least 65536 times as large as the
|
||||||
return offset.plus(min);
|
// 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)
|
static bool is_probably_prime(const UnsignedBigInteger& p)
|
||||||
|
|
|
@ -1419,11 +1419,11 @@ static void hmac_sha512_test_process()
|
||||||
|
|
||||||
static int rsa_tests()
|
static int rsa_tests()
|
||||||
{
|
{
|
||||||
(void)rsa_test_encrypt;
|
rsa_test_encrypt();
|
||||||
(void)rsa_test_der_parse;
|
rsa_test_der_parse();
|
||||||
bigint_test_number_theory();
|
bigint_test_number_theory();
|
||||||
(void)rsa_test_encrypt_decrypt;
|
rsa_test_encrypt_decrypt();
|
||||||
(void)rsa_emsa_pss_test_create;
|
rsa_emsa_pss_test_create();
|
||||||
return g_some_test_failed ? 1 : 0;
|
return g_some_test_failed ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1559,10 +1559,10 @@ static void bigint_test_number_theory()
|
||||||
for (auto test_case : primality_tests) {
|
for (auto test_case : primality_tests) {
|
||||||
I_TEST((Number Theory | Random numbers));
|
I_TEST((Number Theory | Random numbers));
|
||||||
auto actual_result = Crypto::NumberTheory::random_number(test_case.min, test_case.max);
|
auto actual_result = Crypto::NumberTheory::random_number(test_case.min, test_case.max);
|
||||||
if (actual_result < the_min) {
|
if (actual_result < test_case.min) {
|
||||||
FAIL(Too small);
|
FAIL(Too small);
|
||||||
printf("The generated number %s is smaller than the requested minimum %s. (max = %s)\n", actual_result.to_base10().characters(), test_case.min.to_base10().characters(), test_case.max.to_base10().characters());
|
printf("The generated number %s is smaller than the requested minimum %s. (max = %s)\n", actual_result.to_base10().characters(), test_case.min.to_base10().characters(), test_case.max.to_base10().characters());
|
||||||
} else if (!(actual_result < the_max)) {
|
} else if (!(actual_result < test_case.max)) {
|
||||||
FAIL(Too large);
|
FAIL(Too large);
|
||||||
printf("The generated number %s is larger-or-equal to the requested maximum %s. (min = %s)\n", actual_result.to_base10().characters(), test_case.max.to_base10().characters(), test_case.min.to_base10().characters());
|
printf("The generated number %s is larger-or-equal to the requested maximum %s. (min = %s)\n", actual_result.to_base10().characters(), test_case.max.to_base10().characters(), test_case.min.to_base10().characters());
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue