aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/lib/math/numbertheory/make_prm.cpp96
-rwxr-xr-xsrc/scripts/test_cli.py16
-rw-r--r--src/tests/test_bigint.cpp10
3 files changed, 73 insertions, 49 deletions
diff --git a/src/lib/math/numbertheory/make_prm.cpp b/src/lib/math/numbertheory/make_prm.cpp
index 67bdcd678..4a67a1377 100644
--- a/src/lib/math/numbertheory/make_prm.cpp
+++ b/src/lib/math/numbertheory/make_prm.cpp
@@ -1,6 +1,6 @@
/*
* Prime Generation
-* (C) 1999-2007,2018 Jack Lloyd
+* (C) 1999-2007,2018,2019 Jack Lloyd
*
* Botan is released under the Simplified BSD License (see license.txt)
*/
@@ -9,6 +9,8 @@
#include <botan/rng.h>
#include <botan/internal/bit_ops.h>
#include <botan/loadstor.h>
+#include <botan/reducer.h>
+#include <botan/internal/primality.h>
#include <algorithm>
namespace Botan {
@@ -92,35 +94,42 @@ BigInt random_prime(RandomNumberGenerator& rng,
throw Invalid_Argument("random_prime Invalid value for equiv/modulo");
// Handle small values:
- if(bits <= 1)
- {
- throw Invalid_Argument("random_prime: Can't make a prime of " +
- std::to_string(bits) + " bits");
- }
- else if(bits == 2)
- {
- return ((rng.next_byte() % 2) ? 2 : 3);
- }
- else if(bits == 3)
- {
- return ((rng.next_byte() % 2) ? 5 : 7);
- }
- else if(bits == 4)
- {
- return ((rng.next_byte() % 2) ? 11 : 13);
- }
- else if(bits <= 16)
+
+ if(bits <= 16)
{
- for(;;)
+ if(equiv != 1 || modulo != 2 || coprime != 0)
+ throw Not_Implemented("random_prime equiv/modulo/coprime options not usable for small primes");
+
+ if(bits <= 1)
{
- // This is slightly biased, but for small primes it does not seem to matter
- const uint8_t b0 = rng.next_byte();
- const uint8_t b1 = rng.next_byte();
- const size_t idx = make_uint16(b0, b1) % PRIME_TABLE_SIZE;
- const uint16_t small_prime = PRIMES[idx];
-
- if(high_bit(small_prime) == bits)
- return small_prime;
+ throw Invalid_Argument("random_prime: Can't make a prime of " +
+ std::to_string(bits) + " bits");
+ }
+ else if(bits == 2)
+ {
+ return ((rng.next_byte() % 2) ? 2 : 3);
+ }
+ else if(bits == 3)
+ {
+ return ((rng.next_byte() % 2) ? 5 : 7);
+ }
+ else if(bits == 4)
+ {
+ return ((rng.next_byte() % 2) ? 11 : 13);
+ }
+ else
+ {
+ for(;;)
+ {
+ // This is slightly biased, but for small primes it does not seem to matter
+ const uint8_t b0 = rng.next_byte();
+ const uint8_t b1 = rng.next_byte();
+ const size_t idx = make_uint16(b0, b1) % PRIME_TABLE_SIZE;
+ const uint16_t small_prime = PRIMES[idx];
+
+ if(high_bit(small_prime) == bits)
+ return small_prime;
+ }
}
}
@@ -154,7 +163,13 @@ BigInt random_prime(RandomNumberGenerator& rng,
sieve.step(modulo);
- if(sieve.passes(true) == false)
+ // p can be even if modulo is odd, continue on in that case
+ if(p.is_even() || sieve.passes(true) == false)
+ continue;
+
+ Modular_Reducer mod_p(p);
+
+ if(is_miller_rabin_probable_prime(p, mod_p, rng, 1) == false)
continue;
if(coprime > 1)
@@ -166,13 +181,20 @@ BigInt random_prime(RandomNumberGenerator& rng,
* key generation, though RSA keygen should be using generate_rsa_prime.
*/
if(inverse_mod(p - 1, coprime).is_zero())
+ {
continue;
+ }
}
if(p.bits() > bits)
break;
- if(is_prime(p, rng, prob, true))
+ const size_t t = miller_rabin_test_iterations(bits, prob, true);
+
+ if(is_miller_rabin_probable_prime(p, mod_p, rng, t) == false)
+ continue;
+
+ if(is_lucas_probable_prime(p, mod_p))
return p;
}
}
@@ -227,6 +249,16 @@ BigInt generate_rsa_prime(RandomNumberGenerator& keygen_rng,
if(sieve.passes() == false)
continue;
+ Modular_Reducer mod_p(p);
+
+ /*
+ * Do a single primality test first before checking coprimality, since
+ * currently a single Miller-Rabin test is faster than computing modular
+ * inverse, and this eliminates almost all wasted modular inverses.
+ */
+ if(is_miller_rabin_probable_prime(p, mod_p, prime_test_rng, 1) == false)
+ continue;
+
/*
* Check if p - 1 and coprime are relatively prime by computing the inverse.
*
@@ -252,7 +284,9 @@ BigInt generate_rsa_prime(RandomNumberGenerator& keygen_rng,
if(p.bits() > bits)
break;
- if(is_prime(p, prime_test_rng, prob, true))
+ const size_t t = miller_rabin_test_iterations(bits, prob, true);
+
+ if(is_miller_rabin_probable_prime(p, mod_p, prime_test_rng, t) == true)
return p;
}
}
diff --git a/src/scripts/test_cli.py b/src/scripts/test_cli.py
index e449bb74f..ae3ceed18 100755
--- a/src/scripts/test_cli.py
+++ b/src/scripts/test_cli.py
@@ -251,12 +251,12 @@ def cli_argon2_tests(_tmp_dir):
def cli_gen_dl_group_tests(_tmp_dir):
pem = """-----BEGIN X9.42 DH PARAMETERS-----
-MIIBJAKBgwTw7LQiLkXJsrgMVQxTPlWaQlYz/raZ+5RtIZe4YluQgRQGPFADLZ/t
-TOYzuIzZJFOcdKtEtrVkxZRGSkjZwKFKLUD6fzSjoC2M2EHktK/y5HsvxBxL4tKr
-q1ffbyPQi+iBLYTZAXygvxj2vWyrvA+/w4nbt1fStCHTDhWjLWqFpV9nAoGDAKzA
-HUu/IRl7OiUtW/dz36gzEJnaYtz4ZtJl0FG8RJiOe02lD8myqW2sVzYqMvKD0LGx
-x9fdSKC1G+aZ/NWtqrQjb66Daf7b0ddDx+bfWTWJ2dOtZd8IL2rmQQJm+JogDi9i
-huVYFicDNQGzi+nEKAzrZ1L/VxtiSiw/qw0IyOuVtz8CFjgPiPatvmWssQw2AuZ9
+MIIBJAKBgwVcMHlFVo64S86Y5KrlClZrIibOQ6iKm8Ih3Eb53XoQiSc33GtilRmP
+f7qKIVI86meoJHVU7gtaJk82yAYk6BksmZn0eXvUU7zD8yF/yH3yym0SfI0eH1OC
+2+esfGblePpHCtt5uO56pzIqCIpOq+8gTG7JbFHJvTb8nwmAWFLZvjepAoGDBHOP
+e5A/RNyeXz+16+7Jjh4QOXWo/c6kM0WrIHgFbaIkupRndG5bcy8aCjsbgiIpeWy1
+aNDURFB3UR3q1Si0gA7cvirDOH7lnN3C9zeohq+VPy5L7S3gKLGB1HXY/r2qLKhM
+6ziphMYZxtr+XhsbxbA/+MuNoP/He+kwlGLtDKiBdF4CFjgPiPatvmWssQw2AuZ9
mFvAZ/8wal0=
-----END X9.42 DH PARAMETERS-----"""
@@ -904,7 +904,7 @@ def cli_pk_encrypt_tests(tmp_dir):
test_cli("keygen", ["--algo=RSA", "--provider=base", "--params=2048", "--output=%s" % (rsa_priv_key)], "")
- key_hash = "891A3AA179639796B7A6348D2F1C3A8CC7E0FFED38BAE29143DF9B8A55391F28"
+ key_hash = "72AF3227EF57A728E894D54623EB8E2C0CD11A4A98BF2DF32DB052BF60897873"
test_cli("hash", ["--no-fsname", "--algo=SHA-256", rsa_priv_key], key_hash)
test_cli("pkcs8", ["--pub-out", "%s/rsa.priv" % (tmp_dir), "--output=%s" % (rsa_pub_key)], "")
@@ -914,7 +914,7 @@ def cli_pk_encrypt_tests(tmp_dir):
# Because we used a fixed DRBG for each invocation the same ctext is generated each time
rng_output_hash = "32F5E7B61357DE8397EFDA1E598379DFD5EE21767BDF4E2A435F05117B836AC6"
- ctext_hash = "5F45F360CF431C3E1BC126B1DB20CFE7A869AE7B67484A64F426A6349245EB51"
+ ctext_hash = "FF1F0EEC2C42DD61D78505C5DF624A19AE6FE2BAB0B8F7D878C7655D54C68FE0"
test_cli("hash", ["--no-fsname", "--algo=SHA-256", input_file], rng_output_hash)
diff --git a/src/tests/test_bigint.cpp b/src/tests/test_bigint.cpp
index 3ea57d584..283b078ff 100644
--- a/src/tests/test_bigint.cpp
+++ b/src/tests/test_bigint.cpp
@@ -117,16 +117,6 @@ class BigInt_Unit_Tests final : public Test
result.test_eq("P is prime", Botan::is_prime(p, Test::rng()), true);
}
- for(size_t bits = 5; bits <= 32; ++bits)
- {
- const BigInt last_p = p;
- p = Botan::random_prime(Test::rng(), bits, last_p);
-
- result.test_eq("Relatively prime", Botan::gcd(last_p, p), 1);
- result.test_eq("Expected bit size", p.bits(), bits);
- result.test_eq("P is prime", Botan::is_prime(p, Test::rng()), true);
- }
-
const size_t safe_prime_bits = 65;
const BigInt safe_prime = Botan::random_safe_prime(Test::rng(), safe_prime_bits);
result.test_eq("Safe prime size", safe_prime.bits(), safe_prime_bits);