Skip to content
article1,255 words · 6 min read

Arnault's method generates strong pseudoprimes to several bases, this is particularly useful to fool a variant of Miller-Rabin's primality test using a fixed, limited or predictable set of bases.

#Cryptography#Primality#Number theory#Algorithm#Pseudorandom#Pseudoprime

Arnault's method

by neovymp · 21/07/2026

Introduction

This is a (very) shortened version of my Bachelor thesis in Computer Science.

Miller-Rabin primality test

The Miller-Rabin primality test checks for a number's primality by ensuring that there an non-trivial square roots of 11 modulo this number. For a positive odd integer nn and number of rounds rr the test works like this:

  • Factor n1n - 1 as 2kd2^kd.
  • For each round repeat this steps:
    1. Select a random value aa in the interval {2,,n2}\{2, \ldots, n - 2\} called base.
    2. Calculate ad(modn)a^d \pmod n, if this is equal to 11 modulo nn go back to step 1, otherwise proceed to step 3.
    3. If a2id1(modn)a^{2^id} \equiv -1 \pmod n for any 0i<k0 \le i < k go back to step 1 (if it is not the last round), otherwise exit and declare nn composite.
  • If no round deemed nn composite the test deems it prime.

Arnault's method

Arnault's method constructs an odd integer nn product of an odd number of primes p1,p2,,php_1,p_2,\ldots,p_h such that nn is a strong pseudoprimes to a given set of prime bases A={a1,a2,,at}\mathcal{A} = \{a_1,a_2,\ldots,a_t\}. The method construct p1p_1 via a system of equations and then each pip_i as ki(p11)+1k_i(p_1 - 1) + 1 for kik_i randomly chosen to be coprime to each base (except for k1=1k_1 = 1) for 1ih1 \le i \le h. For nn to be a strong pseudoprimes to bases a1,a2,,ata_1,a_2,\ldots,a_t it is sufficient that each of its prime factors pp satisfies (aip)=1\left(\frac{a_i}{p}\right) = -1 (so aia_i is a quadratic nonresidue modulo pp) for 1it1 \le i \le t, where (xy)\left(\frac{x}{y}\right) is the Legendre symbol of xx modulo yy.

Arnault's method starts by generating sets SaS_a for each base aa such that:

p (mod 4a)Sa    (ap)=1p \ (\mathrm{mod}\ 4a) \in S_a \iff \left(\frac{a}{p}\right) = -1

Since p1p_1 has to satisfy the conditions of each set and so do p2,,php_2,\ldots,p_h stricter conditions can be derived:

p1 (mod 4a)Sa=i=1h{ki1(s+ki1) (mod 4a)sSa}p_1 \ (\mathrm{mod}\ 4a) \in S_a' = \bigcap_{i=1}^{h}\{k_i^{-1}(s + k_i - 1) \ (\mathrm{mod}\ 4a) \mid s \in S_a\}

From each of these sets random residues r1,r2,,rtr_1,r_2,\ldots,r_t are chosen to solve a system of equations:

{p1r1 (mod 4a1)p1r2 (mod 4a2)p1rt (mod 4at)\begin{cases} p_1 \equiv r_1 \ (\mathrm{mod}\ 4a_1)\\ p_1 \equiv r_2 \ (\mathrm{mod}\ 4a_2)\\ \vdots\\ p_1 \equiv r_t \ (\mathrm{mod}\ 4a_t) \end{cases}

The CRT tells us a solution is not guaranteed since moduli are not coprime so we may have to try several times (giving up after a few iterations to not fall into the Sunk cost fallacy).

To restrict the field of search a few more conditions can be added, resulting in polynomials for which p1p_1 has to be a root:

fi(x)=ji(kj(x1)+1)1x1 (mod ki)f_i(x) = \frac{\prod_{j \ne i}(k_j(x - 1) + 1) - 1}{x - 1} \ (\mathrm{mod}\ k_i)

After getting a solution (r,m)(r, m) we look for values of qq that make p1=r+qmp_1 = r + qm prime (by simply bruteforcing) and calculate p2,,php_2,\ldots,p_h as described above, if all are prime their product nn will be a strong pseudoprimes to the bases A={a1,a2,,at}\mathcal{A} = \{a_1,a_2,\ldots,a_t\}.

Optimizations

Some sections of Arnault's method slow it down significantly, but with a few clever tricks some optimizations can be found.

Finding p1p_1

To get p1p_1 we must solve the system of equations we saw above, which might take several iterations of the random selection of residues, but a faster strategy is in front of us: instead of picking all residues at once we can select them one at a time, repicking only when there is no solution and continuing like so until the end [1].

find_p1_naive find_p1_smart

Constructing SaS_a

While implementing Arnault's method I noticed a pattern I desperately had to confirm: for a>2a > 2 each set SaS_a contains exactly a1a - 1 elements. After some testing which seemed to confirm my hypothesis I wanted to prove it, which eventually resulted in a two part proof, but first some lemmas:

  1. Dirichlet's theorem an arithmetic progressions states that there are infinitely many primes of the form r+kmr + km for coprime integers rr and mm.
  2. The law of quadratic reciprocity states that (pq)=(1)p12q12(qp)\left(\frac{p}{q}\right) = (-1)^{\frac{p - 1}{2}\frac{q - 1}{2}}\left(\frac{q}{p}\right).

The proof is split in two cases, depending on the value of aa modulo 44:

  1. If a1(mod4)a \equiv 1 \pmod 4 we have (ap)=(pa)\left(\frac{a}{p}\right) = \left(\frac{p}{a}\right) and since aa is fixed for the set SaS_a it is easier to work with the right-hand side. In {1,,a1}\{1, \ldots, a - 1\} there are exactly a12\frac{a - 1}{2} quadratic residues and quadratic nonresidues, we define sets XX and YY with XX containing the odd residues and YY the even ones. Since SaS_a contains primes reduced modulo 4a4a we do not cannot allow even values, meaning elements from the sets {x+axX},{x+3axX},{yyY},{y+2ayY}\{x + a \mid x \in X\}, \{x + 3a \mid x \in X\}, \{y \mid y \in Y\}, \{y + 2a \mid y \in Y\}, leaving to fill SaS_a: X,X={x+2axX},Y={y+ayY},Y={y+3ayY}X, X' = \{x + 2a \mid x \in X\}, Y' = \{y + a \mid y \in Y\}, Y'' = \{y + 3a \mid y \in Y\}, which are trivially disjoint. Therefore Sa=XXYY=2X+2Y=2(X+Y)=2a12=a1\lvert S_a \rvert = \lvert X \cup X' \cup Y' \cup Y'' \rvert = 2\lvert X \rvert + 2\lvert Y \rvert = 2(\lvert X \rvert + \lvert Y \rvert) = 2\frac{a - 1}{2} = a - 1.

  2. For a3(mod4)a \equiv 3 \pmod 4 we do something similar by splitting the set {1,,4a1}\{1, \ldots, 4a - 1\} into two disjoint sets: X={4t+10t<a},Y={4t+30t<a}X = \{4t + 1 \mid 0 \le t < a\}, Y = \{4t + 3 \mid 0 \le t < a\}, with X=Y=a\lvert X \rvert = \lvert Y \rvert = a trivially. Notice that both sets contain all residues modulo aa exactly once and: elements of XX are congruent to 11 modulo 44, implying (ax)=(xa),xX\left(\frac{a}{x}\right) = \left(\frac{x}{a}\right), \forall x \in X, meaning in XX there are a12\frac{a - 1}{2} quadratic nonresidues; meanwhile elements of YY are congruent to 33 modulo 44, implying (ay)=(ya),yy\left(\frac{a}{y}\right) = -\left(\frac{y}{a}\right), \forall y \in y, meaning we need the quadratic residues modulo aa which are once again a12\frac{a - 1}{2}. Combining XX and YY to get SaS_a we finally get Sa=X+Y=a1\lvert S_a \rvert = \lvert X \rvert + \lvert Y \rvert = a - 1.

The steps used in the proof can be made into an algorithm which constructs each set in O(a)\mathcal{O}(a) time:

import gmpy2

def find_Sa(a):
    assert gmpy2.is_prime(a)

    if a % 4 == 1:
        X = set(p for p in range(3, a, 2) if gmpy2.legendre(p, a) == -1)
        Y1 = set(p for p in range(2 + a, 2*a, 2) if gmpy2.legendre(p, a) == -1)
        X1 = set(x + 2*a for x in X)
        Y2 = set(y + 2*a for y in Y1)

        Sa = X | Y1 | X1 | Y2
    else:
        remove = 1 + 4*(-1 * pow(4, -1, a) % a)

        X = set((1 + 4*t) for t in range(a)) - set((remove,))

        X_qnr = set(filter(lambda x: gmpy2.legendre(x, a) == -1, X))
        Y_qr = set((x + 2*a) % (4*a) for x in (X - X_qnr))

        Sa = X_qnr | Y_qr

    return Sa

comparison

The naive strategy tests the condition (ap)=1\left(\frac{a}{p}\right) = -1 for primes in increasing fashion until some arbitrary threshold, which may not find all a1a - 1 of them; stopping instead once a1a - 1 have been found is what the figure is showcasing, which is Ω(aloga)\Omega(a\log a) (empirically).

Conclusions

Fooling a primality test has huge consequences, for example a discrete logarithm can be solved with a much faster method if the modulus used is a composite with known factorization, jeopardizing protocols such as the Diffie-Hellman key exchange which is ubiquitous in public-key cryptography. My implementation of Arnault's method can be found on GitHub.


  1. I had first seen this idea on AMPS18, which was the main inspiration for my thesis. ↩︎