Skip to content

Commit 9b841e7

Browse files
committed
Overhaul of the prime-tests
- Removal of the Fermat test mp_prime_fermat - Replacement of the Strong Lucas-Selfridge test with the Extra Strong Lucas test with Robert Baillie's parameters P = 3 and Q = 1 - Additional tests to check the implementations of the Miller-Rabin and Extra Strong Lucas tests
1 parent 53fdf5f commit 9b841e7

15 files changed

+341
-83
lines changed

demo/test.c

Lines changed: 163 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -896,6 +896,165 @@ static int test_mp_prime_rand(void)
896896
return EXIT_FAILURE;
897897
}
898898

899+
/* Some small pseudoprimes to test the individual implementations */
900+
901+
/* Miller-Rabin base 2 */
902+
static const uint32_t SPSP_2[] = {
903+
2047, 3277, 4033, 4681, 8321, 15841, 29341, 42799,
904+
49141, 52633, 65281, 74665, 80581, 85489, 88357, 90751
905+
};
906+
907+
/* Miller-Rabin base 3 */
908+
static const uint32_t SPSP_3[] = {
909+
121, 703, 1891, 3281, 8401, 8911, 10585, 12403, 16531,
910+
18721, 19345, 23521, 31621, 44287, 47197, 55969, 63139,
911+
74593, 79003, 82513, 87913, 88573, 97567
912+
};
913+
914+
/* SPSP to all bases < 100 */
915+
/* still needs computing
916+
static const char *SPSP_2_100_LARGE[] = {
917+
"",
918+
"",
919+
"",
920+
"",
921+
""
922+
};
923+
*/
924+
925+
/* Extra strong Lucas test with Baillie's parameters Q = 1, P = 3 */
926+
static const uint32_t ESLPSP[] = {
927+
989, 3239, 5777, 10877, 27971, 29681, 30739, 31631, 39059, 72389,
928+
73919, 75077, 100127, 113573, 125249, 137549, 137801, 153931, 155819,
929+
161027, 162133, 189419, 218321, 231703, 249331, 370229, 429479, 430127,
930+
459191, 473891, 480689, 600059, 621781, 632249, 635627
931+
};
932+
933+
/*
934+
Almost extra strong Lucas test with Baillie's parameters Q = 1, P = 3
935+
Only those that are not in ESLPSP.
936+
*/
937+
static const uint32_t AESLPSP[] = {
938+
10469, 154697, 233659, 472453, 629693, 852389, 1091093, 1560437,
939+
1620673, 1813601, 1969109, 2415739, 2595329, 2756837, 3721549,
940+
4269341, 5192309, 7045433, 7226669, 7265561
941+
};
942+
943+
/* Some randomly choosen 200 decimal digits large primes (https://primes.utm.edu/lists/small/small2.html) */
944+
static const char *medium_primes[10] = {
945+
"C8Ckh0vviS3HUPdB1NSrSm+gOodw/f1aQ5+aaH1W6RMB0jVkO6lTaL54O3o7U5BSGUFGxm5gAvisbJamasuLZS8g3ZsJ2JM4Vtn9cQZRfkP6b8V",
946+
"64xDN9FqLBiovZ/9q/EPm0DONpIfn5MbJKHa+IjT0fjAzkg34FpAmad+CwhcpKaiTbZEpErut+DhpVyiQfqBFrgcGnGhhIrMF/XkyY3aVx6E96B",
947+
"8cyuMlENm0vh/eWwgHUpDKqmLyCSsRQZRWvbHpA2jHDZv1EhHkVhceg3OFRZn/aXRBnbdtsc2xO6sWh9KZ5Mo7u9rJgBJMVtDnu094MCExj1YvB",
948+
"BRFZFsYjSz45un8qptnuSqEsy9wV0BzbMpVAB1TrwImENOVIc1cASZNQ/mXG2xtazqgn/juVzFo91XLx9PtIlkcK0L2T6fBNgy8Lc7dSVoKQ+XP",
949+
"Ez/mDl+to2gm69+VdIHI9Q7vaO3DuIdLVT69myM3HYwVBE+G24KffAOUAp3FGrSOU+LtERMiIYIEtxPI7n/DRJtmL2i0+REwGpTMge2d2EpabfB",
950+
"5+Uz1gPFjZJ/nNdEOmOaMouJSGzygo42qz7xOwXn/moSUvBpPjo4twRGbK0+qaeU/RI8yYYxXr3OBP4w+/jgL3mN9GiENDM5LtEKMiQrZ9jIVEb",
951+
"AQ5nD1+G1grv41s/XlK+0YTGyZgr/88PzdQJ8QT9tavisTgyG6k8/80A4HQhnFndskHNAaB2EW5fE7KH3kk7m89s8JnVqkJyGZWSfs1+JlmHLPf",
952+
"3F19vPmM0Ih89KZ04Xmd62QB9F6E2sztT10A7Kcqc44eKvsNHh+JY6Z6gJXkbWg1Iw7xr29QAhEF/o1YAgfutQtpdzHkex06Yd71kPsaZdKXiC5",
953+
"2fIcJ1t/VYCColXGs+ji/txNMEXn2FXdowLzlo7QKqzAWHdAbwtltSO5qpSp3OUiEOGUUi3hbyw3iQRE8nFJaikJ89Wdox6vpPtIsc3QRjexMnv",
954+
"8aOicQ5gIbFCarFUgSgzh40LpuZ0jjK1u48/YT+C0h1dAQ8CIEgZjHZT+5/7cCRGmJlo+XCp7S41MSQ2ZNRSJh2texRYtvAXBAZfR8A8twl316P"
955+
};
956+
957+
#define ARR_LENGTH(a) ((int)(sizeof((a))/sizeof((a)[0])))
958+
959+
static int test_mp_prime_miller_rabin(void)
960+
{
961+
mp_int a, b, c;
962+
bool result;
963+
int i;
964+
DOR(mp_init_multi(&a, &b, &c, NULL));
965+
966+
/* SPSP to base 2 */
967+
mp_set(&b, 2u);
968+
for (i = 0; i < ARR_LENGTH(SPSP_2); i++) {
969+
result = false;
970+
mp_set_u32(&a, SPSP_2[i]);
971+
DO(mp_prime_miller_rabin(&a, &b, &result));
972+
EXPECT(result == true);
973+
}
974+
975+
/* Some larger primes to check for false negatives */
976+
for (i = 0; i < 10; i++) {
977+
result = false;
978+
DO(mp_read_radix(&a, medium_primes[i], 64));
979+
DO(mp_prime_miller_rabin(&a, &b, &result));
980+
EXPECT(result == true);
981+
}
982+
/* Some semi-primes */
983+
for (i = 0; i < 5; i += 2) {
984+
result = false;
985+
DO(mp_read_radix(&a, medium_primes[i], 64));
986+
DO(mp_read_radix(&c, medium_primes[i+1], 64));
987+
DO(mp_mul(&a, &c, &a));
988+
DO(mp_prime_miller_rabin(&a, &b, &result));
989+
EXPECT(result == false);
990+
}
991+
992+
/* SPSP to base 3 */
993+
mp_set(&b, 3u);
994+
for (i = 0; i < ARR_LENGTH(SPSP_3); i++) {
995+
result = false;
996+
mp_set_u32(&a, SPSP_3[i]);
997+
DO(mp_prime_miller_rabin(&a, &b, &result));
998+
EXPECT(result == true);
999+
}
1000+
1001+
mp_clear_multi(&a, &b, &c, NULL);
1002+
return EXIT_SUCCESS;
1003+
LBL_ERR:
1004+
mp_clear_multi(&a, &b, &c, NULL);
1005+
return EXIT_FAILURE;
1006+
}
1007+
1008+
1009+
static int test_mp_prime_extra_strong_lucas(void)
1010+
{
1011+
mp_int a, b;
1012+
bool result;
1013+
int i;
1014+
1015+
DOR(mp_init_multi(&a, &b, NULL));
1016+
1017+
/* Check Extra Strong pseudoprimes */
1018+
for (i = 0; i < ARR_LENGTH(ESLPSP); i++) {
1019+
result = false;
1020+
mp_set_u32(&a, ESLPSP[i]);
1021+
DO(mp_prime_extra_strong_lucas(&a, &result));
1022+
EXPECT(result == true);
1023+
}
1024+
1025+
/* Check Almost Extra Strong pseudoprimes (not in ESLPSP) */
1026+
for (i = 0; i < ARR_LENGTH(AESLPSP); i++) {
1027+
result = false;
1028+
mp_set_u32(&a, AESLPSP[i]);
1029+
DO(mp_prime_extra_strong_lucas(&a, &result));
1030+
EXPECT(result == false);
1031+
}
1032+
1033+
/* Some larger primes to check for false negatives */
1034+
for (i = 0; i < 10; i++) {
1035+
result = false;
1036+
DO(mp_read_radix(&a, medium_primes[i], 64));
1037+
DO(mp_prime_extra_strong_lucas(&a, &result));
1038+
EXPECT(result == true);
1039+
}
1040+
1041+
/* Some semi-primes */
1042+
for (i = 0; i < 5; i++) {
1043+
result = false;
1044+
DO(mp_read_radix(&a, medium_primes[i], 64));
1045+
DO(mp_read_radix(&a, medium_primes[i+1], 64));
1046+
DO(mp_mul(&a, &b, &a));
1047+
DO(mp_prime_extra_strong_lucas(&a, &result));
1048+
EXPECT(result == false);
1049+
}
1050+
1051+
mp_clear_multi(&a, &b, NULL);
1052+
return EXIT_SUCCESS;
1053+
LBL_ERR:
1054+
mp_clear_multi(&a, &b, NULL);
1055+
return EXIT_FAILURE;
1056+
}
1057+
8991058
static int test_mp_prime_is_prime(void)
9001059
{
9011060
int ix;
@@ -965,7 +1124,7 @@ static int test_mp_prime_is_prime(void)
9651124
DO(mp_read_radix(&a,
9661125
"FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF",
9671126
16));
968-
DO(mp_prime_strong_lucas_selfridge(&a, &cnt));
1127+
DO(mp_prime_extra_strong_lucas(&a, &cnt));
9691128
/* large problem */
9701129
EXPECT(cnt);
9711130
if ((e != MP_OKAY) || !cnt) {
@@ -1430,7 +1589,7 @@ static int test_mp_log_n(void)
14301589
mp_int a;
14311590
mp_digit d;
14321591
int base, lb, size;
1433-
const int max_base = MP_MIN(INT_MAX, MP_DIGIT_MAX);
1592+
const mp_digit max_base = MP_MIN(INT_MAX, MP_DIGIT_MAX);
14341593

14351594
DOR(mp_init(&a));
14361595

@@ -2308,6 +2467,8 @@ static int unit_tests(int argc, char **argv)
23082467
T1(mp_montgomery_reduce, MP_MONTGOMERY_REDUCE),
23092468
T1(mp_root_n, MP_ROOT_N),
23102469
T1(mp_or, MP_OR),
2470+
T1(mp_prime_extra_strong_lucas, MP_PRIME_EXTRA_STRONG_LUCAS),
2471+
T1(mp_prime_miller_rabin, MP_PRIME_MILLER_RABIN),
23112472
T1(mp_prime_is_prime, MP_PRIME_IS_PRIME),
23122473
T1(mp_prime_next_prime, MP_PRIME_NEXT_PRIME),
23132474
T1(mp_prime_rand, MP_PRIME_RAND),

doc/bn.tex

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2014,15 +2014,6 @@ \subsection{Example}
20142014

20152015
\chapter{Prime Numbers}
20162016

2017-
\section{Fermat Test}
2018-
\index{mp\_prime\_fermat}
2019-
\begin{alltt}
2020-
mp_err mp_prime_fermat (const mp_int *a, const mp_int *b, int *result)
2021-
\end{alltt}
2022-
Performs a Fermat primality test to the base $b$. That is it computes $b^a \mbox{ mod }a$ and
2023-
tests whether the value is equal to $b$ or not. If the values are equal then $a$ is probably prime
2024-
and $result$ is set to one. Otherwise $result$ is set to zero.
2025-
20262017
\section{Miller--Rabin Test}
20272018
\index{mp\_prime\_miller\_rabin}
20282019
\begin{alltt}
@@ -2032,9 +2023,6 @@ \section{Miller--Rabin Test}
20322023
test and is very hard to fool (besides with Carmichael numbers). If $a$ passes the test (therefore
20332024
is probably prime) $result$ is set to one. Otherwise $result$ is set to zero.
20342025

2035-
Note that it is suggested that you use the Miller--Rabin test instead of the Fermat test since all
2036-
of the failures of Miller--Rabin are a subset of the failures of the Fermat test.
2037-
20382026
\subsection{Required Number of Tests}
20392027
Generally to ensure a number is very likely to be prime you have to perform the Miller--Rabin with
20402028
at least a half--dozen or so unique bases. However, it has been proven that the probability of
@@ -2229,12 +2217,12 @@ \subsection{Required Number of Tests}
22292217

22302218
See also table C.1 in FIPS 186-4.
22312219

2232-
\section{Strong Lucas--Selfridge Test}
2233-
\index{mp\_prime\_strong\_lucas\_selfridge}
2220+
\section{Extra Strong Lucas Test}
2221+
\index{mp\_prime\_extra\_strong\_lucas}
22342222
\begin{alltt}
2235-
mp_err mp_prime_strong_lucas_selfridge(const mp_int *a, bool *result)
2223+
mp_err mp_prime_extra_strong_lucas(const mp_int *a, bool *result)
22362224
\end{alltt}
2237-
Performs a strong Lucas--Selfridge test. The strong Lucas--Selfridge test together with the
2225+
Performs a extra strong Lucas test. The extra strong Lucas test together with the
22382226
Rabin--Miller test with bases $2$ and $3$ resemble the BPSW test. The single internal use is a
22392227
compile--time option in \texttt{mp\_prime\_is\_prime} and can be excluded from the Libtommath build
22402228
if not needed.
@@ -2246,8 +2234,7 @@ \section{Frobenius (Underwood) Test}
22462234
\end{alltt}
22472235
Performs the variant of the Frobenius test as described by Paul Underwood. It can be included at
22482236
build--time if the preprocessor macro \texttt{LTM\_USE\_FROBENIUS\_TEST} is defined and will be
2249-
used
2250-
instead of the Lucas--Selfridge test.
2237+
used instead of the extra strong Lucas test.
22512238

22522239
It returns \texttt{MP\_ITER} if the number of iterations is exhausted, assumes a composite as the
22532240
input and sets \texttt{result} accordingly. This will reduce the set of available pseudoprimes by a

libtommath_VS2008.vcproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -609,7 +609,7 @@
609609
>
610610
</File>
611611
<File
612-
RelativePath="mp_prime_fermat.c"
612+
RelativePath="mp_prime_extra_strong_lucas.c"
613613
>
614614
</File>
615615
<File

makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ mp_get_mag_u64.o mp_get_mag_ul.o mp_grow.o mp_hash.o mp_init.o mp_init_copy.o mp
3535
mp_init_l.o mp_init_multi.o mp_init_set.o mp_init_size.o mp_init_u32.o mp_init_u64.o mp_init_ul.o \
3636
mp_invmod.o mp_is_square.o mp_kronecker.o mp_lcm.o mp_log_n.o mp_lshd.o mp_mod.o mp_mod_2d.o \
3737
mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o mp_mul.o mp_mul_2.o \
38-
mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_fermat.o \
38+
mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_extra_strong_lucas.o \
3939
mp_prime_frobenius_underwood.o mp_prime_is_prime.o mp_prime_miller_rabin.o mp_prime_next_prime.o \
4040
mp_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_radix_size.o \
4141
mp_radix_size_overestimate.o mp_rand.o mp_rand_source.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o \

makefile.mingw

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ mp_get_mag_u64.o mp_get_mag_ul.o mp_grow.o mp_hash.o mp_init.o mp_init_copy.o mp
3737
mp_init_l.o mp_init_multi.o mp_init_set.o mp_init_size.o mp_init_u32.o mp_init_u64.o mp_init_ul.o \
3838
mp_invmod.o mp_is_square.o mp_kronecker.o mp_lcm.o mp_log_n.o mp_lshd.o mp_mod.o mp_mod_2d.o \
3939
mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o mp_mul.o mp_mul_2.o \
40-
mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_fermat.o \
40+
mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_extra_strong_lucas.o \
4141
mp_prime_frobenius_underwood.o mp_prime_is_prime.o mp_prime_miller_rabin.o mp_prime_next_prime.o \
4242
mp_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_radix_size.o \
4343
mp_radix_size_overestimate.o mp_rand.o mp_rand_source.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o \

makefile.msvc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ mp_get_mag_u64.obj mp_get_mag_ul.obj mp_grow.obj mp_hash.obj mp_init.obj mp_init
3333
mp_init_l.obj mp_init_multi.obj mp_init_set.obj mp_init_size.obj mp_init_u32.obj mp_init_u64.obj mp_init_ul.obj \
3434
mp_invmod.obj mp_is_square.obj mp_kronecker.obj mp_lcm.obj mp_log_n.obj mp_lshd.obj mp_mod.obj mp_mod_2d.obj \
3535
mp_montgomery_calc_normalization.obj mp_montgomery_reduce.obj mp_montgomery_setup.obj mp_mul.obj mp_mul_2.obj \
36-
mp_mul_2d.obj mp_mul_d.obj mp_mulmod.obj mp_neg.obj mp_or.obj mp_pack.obj mp_pack_count.obj mp_prime_fermat.obj \
36+
mp_mul_2d.obj mp_mul_d.obj mp_mulmod.obj mp_neg.obj mp_or.obj mp_pack.obj mp_pack_count.obj mp_prime_extra_strong_lucas.obj \
3737
mp_prime_frobenius_underwood.obj mp_prime_is_prime.obj mp_prime_miller_rabin.obj mp_prime_next_prime.obj \
3838
mp_prime_rabin_miller_trials.obj mp_prime_rand.obj mp_prime_strong_lucas_selfridge.obj mp_radix_size.obj \
3939
mp_radix_size_overestimate.obj mp_rand.obj mp_rand_source.obj mp_read_radix.obj mp_reduce.obj mp_reduce_2k.obj \

makefile.shared

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ mp_get_mag_u64.o mp_get_mag_ul.o mp_grow.o mp_hash.o mp_init.o mp_init_copy.o mp
3232
mp_init_l.o mp_init_multi.o mp_init_set.o mp_init_size.o mp_init_u32.o mp_init_u64.o mp_init_ul.o \
3333
mp_invmod.o mp_is_square.o mp_kronecker.o mp_lcm.o mp_log_n.o mp_lshd.o mp_mod.o mp_mod_2d.o \
3434
mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o mp_mul.o mp_mul_2.o \
35-
mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_fermat.o \
35+
mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_extra_strong_lucas.o \
3636
mp_prime_frobenius_underwood.o mp_prime_is_prime.o mp_prime_miller_rabin.o mp_prime_next_prime.o \
3737
mp_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_radix_size.o \
3838
mp_radix_size_overestimate.o mp_rand.o mp_rand_source.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o \

makefile.unix

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ mp_get_mag_u64.o mp_get_mag_ul.o mp_grow.o mp_hash.o mp_init.o mp_init_copy.o mp
3838
mp_init_l.o mp_init_multi.o mp_init_set.o mp_init_size.o mp_init_u32.o mp_init_u64.o mp_init_ul.o \
3939
mp_invmod.o mp_is_square.o mp_kronecker.o mp_lcm.o mp_log_n.o mp_lshd.o mp_mod.o mp_mod_2d.o \
4040
mp_montgomery_calc_normalization.o mp_montgomery_reduce.o mp_montgomery_setup.o mp_mul.o mp_mul_2.o \
41-
mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_fermat.o \
41+
mp_mul_2d.o mp_mul_d.o mp_mulmod.o mp_neg.o mp_or.o mp_pack.o mp_pack_count.o mp_prime_extra_strong_lucas.o \
4242
mp_prime_frobenius_underwood.o mp_prime_is_prime.o mp_prime_miller_rabin.o mp_prime_next_prime.o \
4343
mp_prime_rabin_miller_trials.o mp_prime_rand.o mp_prime_strong_lucas_selfridge.o mp_radix_size.o \
4444
mp_radix_size_overestimate.o mp_rand.o mp_rand_source.o mp_read_radix.o mp_reduce.o mp_reduce_2k.o \

0 commit comments

Comments
 (0)