Dan Willemsen | bbdf664 | 2017-01-13 22:57:23 -0800 | [diff] [blame] | 1 | // Copyright 2016 The Go Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | package big |
| 6 | |
| 7 | import "math/rand" |
| 8 | |
| 9 | // ProbablyPrime reports whether x is probably prime, |
| 10 | // applying the Miller-Rabin test with n pseudorandomly chosen bases |
| 11 | // as well as a Baillie-PSW test. |
| 12 | // |
| 13 | // If x is prime, ProbablyPrime returns true. |
| 14 | // If x is chosen randomly and not prime, ProbablyPrime probably returns false. |
| 15 | // The probability of returning true for a randomly chosen non-prime is at most ¼ⁿ. |
| 16 | // |
| 17 | // ProbablyPrime is 100% accurate for inputs less than 2⁶⁴. |
| 18 | // See Menezes et al., Handbook of Applied Cryptography, 1997, pp. 145-149, |
| 19 | // and FIPS 186-4 Appendix F for further discussion of the error probabilities. |
| 20 | // |
| 21 | // ProbablyPrime is not suitable for judging primes that an adversary may |
| 22 | // have crafted to fool the test. |
| 23 | // |
| 24 | // As of Go 1.8, ProbablyPrime(0) is allowed and applies only a Baillie-PSW test. |
| 25 | // Before Go 1.8, ProbablyPrime applied only the Miller-Rabin tests, and ProbablyPrime(0) panicked. |
| 26 | func (x *Int) ProbablyPrime(n int) bool { |
| 27 | // Note regarding the doc comment above: |
| 28 | // It would be more precise to say that the Baillie-PSW test uses the |
| 29 | // extra strong Lucas test as its Lucas test, but since no one knows |
| 30 | // how to tell any of the Lucas tests apart inside a Baillie-PSW test |
| 31 | // (they all work equally well empirically), that detail need not be |
| 32 | // documented or implicitly guaranteed. |
| 33 | // The comment does avoid saying "the" Baillie-PSW test |
| 34 | // because of this general ambiguity. |
| 35 | |
| 36 | if n < 0 { |
| 37 | panic("negative n for ProbablyPrime") |
| 38 | } |
| 39 | if x.neg || len(x.abs) == 0 { |
| 40 | return false |
| 41 | } |
| 42 | |
| 43 | // primeBitMask records the primes < 64. |
| 44 | const primeBitMask uint64 = 1<<2 | 1<<3 | 1<<5 | 1<<7 | |
| 45 | 1<<11 | 1<<13 | 1<<17 | 1<<19 | 1<<23 | 1<<29 | 1<<31 | |
| 46 | 1<<37 | 1<<41 | 1<<43 | 1<<47 | 1<<53 | 1<<59 | 1<<61 |
| 47 | |
| 48 | w := x.abs[0] |
| 49 | if len(x.abs) == 1 && w < 64 { |
| 50 | return primeBitMask&(1<<w) != 0 |
| 51 | } |
| 52 | |
| 53 | if w&1 == 0 { |
Colin Cross | 1371fe4 | 2019-03-19 21:08:48 -0700 | [diff] [blame] | 54 | return false // x is even |
Dan Willemsen | bbdf664 | 2017-01-13 22:57:23 -0800 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | const primesA = 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23 * 37 |
| 58 | const primesB = 29 * 31 * 41 * 43 * 47 * 53 |
| 59 | |
| 60 | var rA, rB uint32 |
| 61 | switch _W { |
| 62 | case 32: |
| 63 | rA = uint32(x.abs.modW(primesA)) |
| 64 | rB = uint32(x.abs.modW(primesB)) |
| 65 | case 64: |
| 66 | r := x.abs.modW((primesA * primesB) & _M) |
| 67 | rA = uint32(r % primesA) |
| 68 | rB = uint32(r % primesB) |
| 69 | default: |
| 70 | panic("math/big: invalid word size") |
| 71 | } |
| 72 | |
| 73 | if rA%3 == 0 || rA%5 == 0 || rA%7 == 0 || rA%11 == 0 || rA%13 == 0 || rA%17 == 0 || rA%19 == 0 || rA%23 == 0 || rA%37 == 0 || |
| 74 | rB%29 == 0 || rB%31 == 0 || rB%41 == 0 || rB%43 == 0 || rB%47 == 0 || rB%53 == 0 { |
| 75 | return false |
| 76 | } |
| 77 | |
| 78 | return x.abs.probablyPrimeMillerRabin(n+1, true) && x.abs.probablyPrimeLucas() |
| 79 | } |
| 80 | |
| 81 | // probablyPrimeMillerRabin reports whether n passes reps rounds of the |
| 82 | // Miller-Rabin primality test, using pseudo-randomly chosen bases. |
| 83 | // If force2 is true, one of the rounds is forced to use base 2. |
| 84 | // See Handbook of Applied Cryptography, p. 139, Algorithm 4.24. |
| 85 | // The number n is known to be non-zero. |
| 86 | func (n nat) probablyPrimeMillerRabin(reps int, force2 bool) bool { |
| 87 | nm1 := nat(nil).sub(n, natOne) |
| 88 | // determine q, k such that nm1 = q << k |
| 89 | k := nm1.trailingZeroBits() |
| 90 | q := nat(nil).shr(nm1, k) |
| 91 | |
| 92 | nm3 := nat(nil).sub(nm1, natTwo) |
| 93 | rand := rand.New(rand.NewSource(int64(n[0]))) |
| 94 | |
| 95 | var x, y, quotient nat |
| 96 | nm3Len := nm3.bitLen() |
| 97 | |
| 98 | NextRandom: |
| 99 | for i := 0; i < reps; i++ { |
| 100 | if i == reps-1 && force2 { |
| 101 | x = x.set(natTwo) |
| 102 | } else { |
| 103 | x = x.random(rand, nm3, nm3Len) |
| 104 | x = x.add(x, natTwo) |
| 105 | } |
Dan Willemsen | b8ef64a | 2023-04-04 01:48:15 -0400 | [diff] [blame^] | 106 | y = y.expNN(x, q, n, false) |
Dan Willemsen | bbdf664 | 2017-01-13 22:57:23 -0800 | [diff] [blame] | 107 | if y.cmp(natOne) == 0 || y.cmp(nm1) == 0 { |
| 108 | continue |
| 109 | } |
| 110 | for j := uint(1); j < k; j++ { |
Dan Willemsen | e1b3b18 | 2018-02-27 19:36:27 -0800 | [diff] [blame] | 111 | y = y.sqr(y) |
Dan Willemsen | bbdf664 | 2017-01-13 22:57:23 -0800 | [diff] [blame] | 112 | quotient, y = quotient.div(y, y, n) |
| 113 | if y.cmp(nm1) == 0 { |
| 114 | continue NextRandom |
| 115 | } |
| 116 | if y.cmp(natOne) == 0 { |
| 117 | return false |
| 118 | } |
| 119 | } |
| 120 | return false |
| 121 | } |
| 122 | |
| 123 | return true |
| 124 | } |
| 125 | |
| 126 | // probablyPrimeLucas reports whether n passes the "almost extra strong" Lucas probable prime test, |
| 127 | // using Baillie-OEIS parameter selection. This corresponds to "AESLPSP" on Jacobsen's tables (link below). |
| 128 | // The combination of this test and a Miller-Rabin/Fermat test with base 2 gives a Baillie-PSW test. |
| 129 | // |
| 130 | // References: |
| 131 | // |
| 132 | // Baillie and Wagstaff, "Lucas Pseudoprimes", Mathematics of Computation 35(152), |
| 133 | // October 1980, pp. 1391-1417, especially page 1401. |
Dan Willemsen | f3f2eb6 | 2018-08-28 11:28:58 -0700 | [diff] [blame] | 134 | // https://www.ams.org/journals/mcom/1980-35-152/S0025-5718-1980-0583518-6/S0025-5718-1980-0583518-6.pdf |
Dan Willemsen | bbdf664 | 2017-01-13 22:57:23 -0800 | [diff] [blame] | 135 | // |
| 136 | // Grantham, "Frobenius Pseudoprimes", Mathematics of Computation 70(234), |
| 137 | // March 2000, pp. 873-891. |
Dan Willemsen | f3f2eb6 | 2018-08-28 11:28:58 -0700 | [diff] [blame] | 138 | // https://www.ams.org/journals/mcom/2001-70-234/S0025-5718-00-01197-2/S0025-5718-00-01197-2.pdf |
Dan Willemsen | bbdf664 | 2017-01-13 22:57:23 -0800 | [diff] [blame] | 139 | // |
| 140 | // Baillie, "Extra strong Lucas pseudoprimes", OEIS A217719, https://oeis.org/A217719. |
| 141 | // |
| 142 | // Jacobsen, "Pseudoprime Statistics, Tables, and Data", http://ntheory.org/pseudoprimes.html. |
| 143 | // |
Dan Willemsen | b8ef64a | 2023-04-04 01:48:15 -0400 | [diff] [blame^] | 144 | // Nicely, "The Baillie-PSW Primality Test", https://web.archive.org/web/20191121062007/http://www.trnicely.net/misc/bpsw.html. |
Dan Willemsen | bbdf664 | 2017-01-13 22:57:23 -0800 | [diff] [blame] | 145 | // (Note that Nicely's definition of the "extra strong" test gives the wrong Jacobi condition, |
| 146 | // as pointed out by Jacobsen.) |
| 147 | // |
| 148 | // Crandall and Pomerance, Prime Numbers: A Computational Perspective, 2nd ed. |
| 149 | // Springer, 2005. |
| 150 | func (n nat) probablyPrimeLucas() bool { |
| 151 | // Discard 0, 1. |
| 152 | if len(n) == 0 || n.cmp(natOne) == 0 { |
| 153 | return false |
| 154 | } |
| 155 | // Two is the only even prime. |
| 156 | // Already checked by caller, but here to allow testing in isolation. |
| 157 | if n[0]&1 == 0 { |
| 158 | return n.cmp(natTwo) == 0 |
| 159 | } |
| 160 | |
| 161 | // Baillie-OEIS "method C" for choosing D, P, Q, |
| 162 | // as in https://oeis.org/A217719/a217719.txt: |
| 163 | // try increasing P ≥ 3 such that D = P² - 4 (so Q = 1) |
| 164 | // until Jacobi(D, n) = -1. |
| 165 | // The search is expected to succeed for non-square n after just a few trials. |
| 166 | // After more than expected failures, check whether n is square |
| 167 | // (which would cause Jacobi(D, n) = 1 for all D not dividing n). |
| 168 | p := Word(3) |
| 169 | d := nat{1} |
| 170 | t1 := nat(nil) // temp |
| 171 | intD := &Int{abs: d} |
| 172 | intN := &Int{abs: n} |
| 173 | for ; ; p++ { |
| 174 | if p > 10000 { |
| 175 | // This is widely believed to be impossible. |
| 176 | // If we get a report, we'll want the exact number n. |
| 177 | panic("math/big: internal error: cannot find (D/n) = -1 for " + intN.String()) |
| 178 | } |
| 179 | d[0] = p*p - 4 |
| 180 | j := Jacobi(intD, intN) |
| 181 | if j == -1 { |
| 182 | break |
| 183 | } |
| 184 | if j == 0 { |
| 185 | // d = p²-4 = (p-2)(p+2). |
| 186 | // If (d/n) == 0 then d shares a prime factor with n. |
| 187 | // Since the loop proceeds in increasing p and starts with p-2==1, |
| 188 | // the shared prime factor must be p+2. |
| 189 | // If p+2 == n, then n is prime; otherwise p+2 is a proper factor of n. |
| 190 | return len(n) == 1 && n[0] == p+2 |
| 191 | } |
| 192 | if p == 40 { |
| 193 | // We'll never find (d/n) = -1 if n is a square. |
| 194 | // If n is a non-square we expect to find a d in just a few attempts on average. |
| 195 | // After 40 attempts, take a moment to check if n is indeed a square. |
| 196 | t1 = t1.sqrt(n) |
Dan Willemsen | e1b3b18 | 2018-02-27 19:36:27 -0800 | [diff] [blame] | 197 | t1 = t1.sqr(t1) |
Dan Willemsen | bbdf664 | 2017-01-13 22:57:23 -0800 | [diff] [blame] | 198 | if t1.cmp(n) == 0 { |
| 199 | return false |
| 200 | } |
| 201 | } |
| 202 | } |
| 203 | |
| 204 | // Grantham definition of "extra strong Lucas pseudoprime", after Thm 2.3 on p. 876 |
| 205 | // (D, P, Q above have become Δ, b, 1): |
| 206 | // |
| 207 | // Let U_n = U_n(b, 1), V_n = V_n(b, 1), and Δ = b²-4. |
| 208 | // An extra strong Lucas pseudoprime to base b is a composite n = 2^r s + Jacobi(Δ, n), |
| 209 | // where s is odd and gcd(n, 2*Δ) = 1, such that either (i) U_s ≡ 0 mod n and V_s ≡ ±2 mod n, |
| 210 | // or (ii) V_{2^t s} ≡ 0 mod n for some 0 ≤ t < r-1. |
| 211 | // |
| 212 | // We know gcd(n, Δ) = 1 or else we'd have found Jacobi(d, n) == 0 above. |
| 213 | // We know gcd(n, 2) = 1 because n is odd. |
| 214 | // |
| 215 | // Arrange s = (n - Jacobi(Δ, n)) / 2^r = (n+1) / 2^r. |
| 216 | s := nat(nil).add(n, natOne) |
| 217 | r := int(s.trailingZeroBits()) |
| 218 | s = s.shr(s, uint(r)) |
| 219 | nm2 := nat(nil).sub(n, natTwo) // n-2 |
| 220 | |
| 221 | // We apply the "almost extra strong" test, which checks the above conditions |
| 222 | // except for U_s ≡ 0 mod n, which allows us to avoid computing any U_k values. |
| 223 | // Jacobsen points out that maybe we should just do the full extra strong test: |
| 224 | // "It is also possible to recover U_n using Crandall and Pomerance equation 3.13: |
| 225 | // U_n = D^-1 (2V_{n+1} - PV_n) allowing us to run the full extra-strong test |
| 226 | // at the cost of a single modular inversion. This computation is easy and fast in GMP, |
| 227 | // so we can get the full extra-strong test at essentially the same performance as the |
| 228 | // almost extra strong test." |
| 229 | |
| 230 | // Compute Lucas sequence V_s(b, 1), where: |
| 231 | // |
| 232 | // V(0) = 2 |
| 233 | // V(1) = P |
| 234 | // V(k) = P V(k-1) - Q V(k-2). |
| 235 | // |
| 236 | // (Remember that due to method C above, P = b, Q = 1.) |
| 237 | // |
| 238 | // In general V(k) = α^k + β^k, where α and β are roots of x² - Px + Q. |
| 239 | // Crandall and Pomerance (p.147) observe that for 0 ≤ j ≤ k, |
| 240 | // |
| 241 | // V(j+k) = V(j)V(k) - V(k-j). |
| 242 | // |
| 243 | // So in particular, to quickly double the subscript: |
| 244 | // |
| 245 | // V(2k) = V(k)² - 2 |
| 246 | // V(2k+1) = V(k) V(k+1) - P |
| 247 | // |
| 248 | // We can therefore start with k=0 and build up to k=s in log₂(s) steps. |
| 249 | natP := nat(nil).setWord(p) |
| 250 | vk := nat(nil).setWord(2) |
| 251 | vk1 := nat(nil).setWord(p) |
| 252 | t2 := nat(nil) // temp |
| 253 | for i := int(s.bitLen()); i >= 0; i-- { |
| 254 | if s.bit(uint(i)) != 0 { |
| 255 | // k' = 2k+1 |
| 256 | // V(k') = V(2k+1) = V(k) V(k+1) - P. |
| 257 | t1 = t1.mul(vk, vk1) |
| 258 | t1 = t1.add(t1, n) |
| 259 | t1 = t1.sub(t1, natP) |
| 260 | t2, vk = t2.div(vk, t1, n) |
| 261 | // V(k'+1) = V(2k+2) = V(k+1)² - 2. |
Dan Willemsen | e1b3b18 | 2018-02-27 19:36:27 -0800 | [diff] [blame] | 262 | t1 = t1.sqr(vk1) |
Dan Willemsen | bbdf664 | 2017-01-13 22:57:23 -0800 | [diff] [blame] | 263 | t1 = t1.add(t1, nm2) |
| 264 | t2, vk1 = t2.div(vk1, t1, n) |
| 265 | } else { |
| 266 | // k' = 2k |
| 267 | // V(k'+1) = V(2k+1) = V(k) V(k+1) - P. |
| 268 | t1 = t1.mul(vk, vk1) |
| 269 | t1 = t1.add(t1, n) |
| 270 | t1 = t1.sub(t1, natP) |
| 271 | t2, vk1 = t2.div(vk1, t1, n) |
| 272 | // V(k') = V(2k) = V(k)² - 2 |
Dan Willemsen | e1b3b18 | 2018-02-27 19:36:27 -0800 | [diff] [blame] | 273 | t1 = t1.sqr(vk) |
Dan Willemsen | bbdf664 | 2017-01-13 22:57:23 -0800 | [diff] [blame] | 274 | t1 = t1.add(t1, nm2) |
| 275 | t2, vk = t2.div(vk, t1, n) |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | // Now k=s, so vk = V(s). Check V(s) ≡ ±2 (mod n). |
| 280 | if vk.cmp(natTwo) == 0 || vk.cmp(nm2) == 0 { |
| 281 | // Check U(s) ≡ 0. |
| 282 | // As suggested by Jacobsen, apply Crandall and Pomerance equation 3.13: |
| 283 | // |
| 284 | // U(k) = D⁻¹ (2 V(k+1) - P V(k)) |
| 285 | // |
| 286 | // Since we are checking for U(k) == 0 it suffices to check 2 V(k+1) == P V(k) mod n, |
| 287 | // or P V(k) - 2 V(k+1) == 0 mod n. |
| 288 | t1 := t1.mul(vk, natP) |
| 289 | t2 := t2.shl(vk1, 1) |
| 290 | if t1.cmp(t2) < 0 { |
| 291 | t1, t2 = t2, t1 |
| 292 | } |
| 293 | t1 = t1.sub(t1, t2) |
| 294 | t3 := vk1 // steal vk1, no longer needed below |
| 295 | vk1 = nil |
| 296 | _ = vk1 |
| 297 | t2, t3 = t2.div(t3, t1, n) |
| 298 | if len(t3) == 0 { |
| 299 | return true |
| 300 | } |
| 301 | } |
| 302 | |
| 303 | // Check V(2^t s) ≡ 0 mod n for some 0 ≤ t < r-1. |
| 304 | for t := 0; t < r-1; t++ { |
| 305 | if len(vk) == 0 { // vk == 0 |
| 306 | return true |
| 307 | } |
| 308 | // Optimization: V(k) = 2 is a fixed point for V(k') = V(k)² - 2, |
| 309 | // so if V(k) = 2, we can stop: we will never find a future V(k) == 0. |
| 310 | if len(vk) == 1 && vk[0] == 2 { // vk == 2 |
| 311 | return false |
| 312 | } |
| 313 | // k' = 2k |
| 314 | // V(k') = V(2k) = V(k)² - 2 |
Dan Willemsen | e1b3b18 | 2018-02-27 19:36:27 -0800 | [diff] [blame] | 315 | t1 = t1.sqr(vk) |
Dan Willemsen | bbdf664 | 2017-01-13 22:57:23 -0800 | [diff] [blame] | 316 | t1 = t1.sub(t1, natTwo) |
| 317 | t2, vk = t2.div(vk, t1, n) |
| 318 | } |
| 319 | return false |
| 320 | } |