mirror of
https://github.com/saymrwulf/risc0-ed25519-verified.git
synced 2026-09-04 20:03:41 +00:00
553 lines
36 KiB
Text
553 lines
36 KiB
Text
|
|
/-
|
|||
|
|
═══════════════════════════════════════════════════════════════════════════════
|
|||
|
|
Proofs/P25519.lean — primality of the Curve25519 base-field modulus
|
|||
|
|
p = 2^255 − 19, via Lucas/Pratt certificates
|
|||
|
|
═══════════════════════════════════════════════════════════════════════════════
|
|||
|
|
|
|||
|
|
WHAT THIS FILE PROVES
|
|||
|
|
`p25519_prime : Nat.Prime (2 ^ 255 - 19)` — the 255-bit modulus of the field
|
|||
|
|
F_p implemented by the Rust crate is a prime number. Axiom-free, with no
|
|||
|
|
`native_decide`: every numeric fact is checked by the Lean KERNEL (`decide`)
|
|||
|
|
through a purpose-built binary modular-exponentiation function (`powMod`).
|
|||
|
|
|
|||
|
|
WHY THE FIELD VERIFICATION NEEDS THIS FILE
|
|||
|
|
* Mathlib only provides the `Field (ZMod P)` instance — i.e. "F_p really is a
|
|||
|
|
field, with all field axioms" — from `Fact (Nat.Prime P)`. The main theorem
|
|||
|
|
(Proofs/FieldMain.lean, `fieldImplementation`) states that the transpiled
|
|||
|
|
Rust code implements exactly that field, so primality is a prerequisite for
|
|||
|
|
even *stating* the result. Proofs/Field.lean consumes `p25519_prime` to
|
|||
|
|
build `P_prime : Nat.Prime P` and the `Fact`/`NeZero` instances.
|
|||
|
|
* Rust analog (indirect — this file contains no transpiled code):
|
|||
|
|
`FieldElement::invert`, curve25519/solana-ed25519/src/field.rs:239-248,
|
|||
|
|
computes x^(p−2) and its doc comment justifies this with
|
|||
|
|
"x^(p-2)·x = x^(p-1) = 1 (mod p)" — Fermat's little theorem, which is
|
|||
|
|
only valid because p is prime. Proofs/InvertSpec.lean formalizes exactly
|
|||
|
|
that argument and needs the primality proved here.
|
|||
|
|
|
|||
|
|
PLACE IN THE IMPORT GRAPH
|
|||
|
|
Leaf: imports only mathlib (LucasPrimality, ZMod, norm_num-prime).
|
|||
|
|
Imported by Proofs/Field.lean, and through it by Proofs/InvertSpec.lean and
|
|||
|
|
Proofs/FieldMain.lean.
|
|||
|
|
|
|||
|
|
THE PROOF TECHNIQUE, FOR THE LAY READER (Lucas test / Pratt certificates)
|
|||
|
|
How do you convince a proof CHECKER that a 255-bit number n is prime without
|
|||
|
|
trial division up to 2^127? Use the classical Lucas test (the basis of
|
|||
|
|
"Pratt certificates", the textbook proof that PRIMES ∈ NP):
|
|||
|
|
|
|||
|
|
if some witness g satisfies
|
|||
|
|
(1) g^(n−1) ≡ 1 (mod n) (Fermat condition)
|
|||
|
|
(2) g^((n−1)/q) ≢ 1 (mod n) for EVERY prime q dividing n−1,
|
|||
|
|
then n is prime.
|
|||
|
|
|
|||
|
|
Why this works: (1) says the multiplicative order of g modulo n divides n−1;
|
|||
|
|
if that order were a PROPER divisor of n−1 it would divide (n−1)/q for some
|
|||
|
|
prime q | n−1, contradicting (2). So g has order exactly n−1 in the unit
|
|||
|
|
group of Z/n. But that group has only φ(n) ≤ n−1 elements, so an element of
|
|||
|
|
order n−1 can exist only if φ(n) = n−1 — which happens precisely when n is
|
|||
|
|
prime. Mathlib packages this as `lucas_primality`.
|
|||
|
|
|
|||
|
|
The catch: condition (2) needs the COMPLETE prime factorization of n−1, and
|
|||
|
|
each prime factor q must itself be certified prime — recursively, by the
|
|||
|
|
same test. The recursion bottoms out at factors small enough for mathlib's
|
|||
|
|
`norm_num` prime checker. The published factor tree used below (any
|
|||
|
|
factoring tool reproduces it; the kernel re-verifies every product):
|
|||
|
|
|
|||
|
|
p − 1 = 2^2 · 3 · 65147 · q1, p = 2^255 − 19
|
|||
|
|
q1 = 740582127325613583022312264370627\
|
|||
|
|
88676166966415465897661863160754340907 (236 bits)
|
|||
|
|
q1 − 1 = 2 · 3 · 353 · 57467 · 132049 · 1923133 · q2 · q3
|
|||
|
|
q2 = 31757755568855353
|
|||
|
|
q2 − 1 = 2^3 · 3 · 31 · 107 · 223 · 4153 · 430751 (all small)
|
|||
|
|
q3 = 75445702479781427272750846543864801
|
|||
|
|
q3 − 1 = 2^5 · 3^2 · 5^2 · 75707 · q4 · q5
|
|||
|
|
q4 = 72106336199
|
|||
|
|
q4 − 1 = 2 · 13 · q6
|
|||
|
|
q6 = 2773320623, q6 − 1 = 2 · 2437 · 569003 (all small)
|
|||
|
|
q5 = 1919519569386763
|
|||
|
|
q5 − 1 = 2 · 3 · 7 · 19 · 47^2 · 127 · q7
|
|||
|
|
q7 = 8574133, q7 − 1 = 2^2 · 3 · 7 · 103 · 991 (all small)
|
|||
|
|
|
|||
|
|
The certificate theorems below appear leaves-first:
|
|||
|
|
q7, q6, q4, q5, q2, q3, q1, and finally p itself.
|
|||
|
|
|
|||
|
|
WHY `powMod` EXISTS
|
|||
|
|
Checking condition (1) for p means verifying a congruence with a 255-bit
|
|||
|
|
exponent. `decide` on `(2 : ZMod n) ^ (n−1) = 1` directly is hopeless: `^`
|
|||
|
|
on `ZMod n` unfolds to n−1 ≈ 2^255 repeated multiplications. Instead we
|
|||
|
|
define square-and-multiply on raw `Nat` (`powModAux`), prove ONCE that it
|
|||
|
|
computes `a ^ k % n` (`powModAux_eq`), and then every certificate condition
|
|||
|
|
becomes a closed equation `powMod a k n = 1` (or `≠ 1`) between `Nat`
|
|||
|
|
literals. Lean's kernel evaluates `Nat` literal arithmetic (·, %, /) with
|
|||
|
|
GMP big-integer primitives, so each such `decide` costs ~256 squarings of
|
|||
|
|
≤255-bit numbers — milliseconds, entirely inside the trusted kernel.
|
|||
|
|
-/
|
|||
|
|
import Mathlib.NumberTheory.LucasPrimality
|
|||
|
|
import Mathlib.Data.ZMod.Basic
|
|||
|
|
import Mathlib.Tactic.NormNum.Prime
|
|||
|
|
|
|||
|
|
-- Elaborating `decide` on the huge decimal literals below builds deep numeral
|
|||
|
|
-- terms; raise the elaborator's recursion limit so they go through.
|
|||
|
|
set_option maxRecDepth 8000
|
|||
|
|
|
|||
|
|
-- All helpers and per-node certificates live in their own namespace; only the
|
|||
|
|
-- final `p25519_prime` (stated about `2 ^ 255 - 19` itself) is exported at top
|
|||
|
|
-- level for Proofs/Field.lean.
|
|||
|
|
namespace P25519
|
|||
|
|
|
|||
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|||
|
|
-- Kernel-checkable modular exponentiation
|
|||
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
/-- Fuel-based binary modular exponentiation, kernel-reducible (GMP-fast `decide`).
|
|||
|
|
|
|||
|
|
MATH (for sufficient fuel; made precise by `powModAux_eq`):
|
|||
|
|
`powModAux fuel a k n = a^k mod n`.
|
|||
|
|
Algorithm: square-and-multiply, consuming the binary digits of `k` from the
|
|||
|
|
low end —
|
|||
|
|
k = 0 ↦ 1 mod n
|
|||
|
|
k = 2m ↦ (a² mod n)^m mod n
|
|||
|
|
k = 2m+1 ↦ ((a² mod n)^m mod n) · a mod n
|
|||
|
|
Every intermediate is reduced mod n, so no value ever exceeds n² (≈510 bits
|
|||
|
|
here) — this is what keeps kernel evaluation fast.
|
|||
|
|
|
|||
|
|
WHY THE `fuel` ARGUMENT: recursion is on `fuel` (plain structural recursion),
|
|||
|
|
not on `k`. Recursing on `k/2 < k` would be well-founded recursion, which
|
|||
|
|
Lean compiles to `WellFounded.fix` — a fixpoint the kernel cannot unfold
|
|||
|
|
during `decide`. With fuel, the kernel just peels one constructor per step.
|
|||
|
|
|
|||
|
|
WHY NEEDED: this is the workhorse that lets the kernel verify 255-bit
|
|||
|
|
Fermat-witness congruences in milliseconds (see file header). -/
|
|||
|
|
def powModAux : Nat → Nat → Nat → Nat → Nat
|
|||
|
|
| 0, _, _, n => 1 % n
|
|||
|
|
| fuel + 1, a, k, n =>
|
|||
|
|
if k = 0 then 1 % n
|
|||
|
|
else if k % 2 = 1 then powModAux fuel (a * a % n) (k / 2) n * a % n
|
|||
|
|
else powModAux fuel (a * a % n) (k / 2) n
|
|||
|
|
|
|||
|
|
/- Correctness of `powModAux`.
|
|||
|
|
|
|||
|
|
MATH (ASCII): forall fuel a k n, k < 2^fuel ==>
|
|||
|
|
powModAux fuel a k n = a^k mod n
|
|||
|
|
LaTeX: $\forall\,\mathit{fuel}\,a\,k\,n,\ k < 2^{\mathit{fuel}}
|
|||
|
|
\Rightarrow \mathrm{powModAux}\ \mathit{fuel}\ a\ k\ n = a^k \bmod n$
|
|||
|
|
The hypothesis `k < 2^fuel` says the fuel covers every binary digit of the
|
|||
|
|
exponent, so the recursion never runs dry.
|
|||
|
|
|
|||
|
|
WHY NEEDED: turns each kernel computation `powMod a k n = …` into the
|
|||
|
|
mathematical statement `a^k % n = …` that `lucas_primality` needs.
|
|||
|
|
Proof: induction on `fuel`, mirroring the recursion of `powModAux`. -/
|
|||
|
|
theorem powModAux_eq : ∀ (fuel a k n : ℕ), k < 2 ^ fuel → powModAux fuel a k n = a ^ k % n := by
|
|||
|
|
intro fuel
|
|||
|
|
induction fuel with
|
|||
|
|
| zero =>
|
|||
|
|
-- base case: k < 2^0 = 1 forces k = 0, and both sides reduce to 1 % n
|
|||
|
|
intro a k n hk
|
|||
|
|
rw [pow_zero] at hk
|
|||
|
|
have hk0 : k = 0 := by omega
|
|||
|
|
subst hk0
|
|||
|
|
simp [powModAux]
|
|||
|
|
| succ f ih =>
|
|||
|
|
intro a k n hk
|
|||
|
|
by_cases hk0 : k = 0
|
|||
|
|
-- k = 0: both sides are 1 % n by definition
|
|||
|
|
· subst hk0; simp [powModAux]
|
|||
|
|
-- k ≠ 0: the recursive call gets exponent k/2, which fits in f bits…
|
|||
|
|
· have hk2 : k / 2 < 2 ^ f := by
|
|||
|
|
rw [pow_succ] at hk
|
|||
|
|
omega
|
|||
|
|
-- …so the induction hypothesis describes it: (a²%n)^(k/2) % n
|
|||
|
|
have hrec := ih (a * a % n) (k / 2) n hk2
|
|||
|
|
have haa : a * a = a ^ 2 := (pow_two a).symm
|
|||
|
|
simp only [powModAux, if_neg hk0]
|
|||
|
|
-- split on the lowest bit of k and reassemble the exponent:
|
|||
|
|
by_cases hodd : k % 2 = 1
|
|||
|
|
-- odd k: (a²)^(k/2) · a = a^(2·(k/2)+1) = a^k (mods commute via Nat.pow_mod)
|
|||
|
|
· rw [if_pos hodd, hrec, ← Nat.pow_mod, Nat.mod_mul_mod, haa, ← pow_mul, ← pow_succ,
|
|||
|
|
show 2 * (k / 2) + 1 = k by omega]
|
|||
|
|
-- even k: (a²)^(k/2) = a^(2·(k/2)) = a^k
|
|||
|
|
· rw [if_neg hodd, hrec, ← Nat.pow_mod, haa, ← pow_mul,
|
|||
|
|
show 2 * (k / 2) = k by omega]
|
|||
|
|
|
|||
|
|
/-- `powMod a k n = a ^ k % n` for all `k < 2 ^ 256`.
|
|||
|
|
|
|||
|
|
The fuel is fixed at 256: enough for any exponent below 2^256, in particular
|
|||
|
|
for every exponent `(n−1)/q` appearing in the certificates (n ≤ p < 2^255).
|
|||
|
|
|
|||
|
|
WHY NEEDED: the single entry point all certificate side-conditions are stated
|
|||
|
|
through, so each becomes one GMP-fast kernel `decide`. -/
|
|||
|
|
def powMod (a k n : ℕ) : ℕ := powModAux 256 a k n
|
|||
|
|
|
|||
|
|
/- Bridge from the `Nat` computation into `ZMod n`, where `lucas_primality`
|
|||
|
|
lives.
|
|||
|
|
|
|||
|
|
MATH: k < 2^256 ==> (a : ZMod n)^k = (powMod a k n : ZMod n)
|
|||
|
|
i.e. casting `a` to Z/n and exponentiating there agrees with computing
|
|||
|
|
`a^k mod n` over the naturals and casting the result. Follows from
|
|||
|
|
`powModAux_eq` plus the fact that the cast Nat → ZMod n is a ring
|
|||
|
|
homomorphism that kills `% n`.
|
|||
|
|
|
|||
|
|
WHY NEEDED: the two lemmas below (`pow_eq_one_of_powMod`,
|
|||
|
|
`pow_ne_one_of_powMod`) are corollaries of this one. -/
|
|||
|
|
theorem cast_pow_eq (a k n : ℕ) (hk : k < 2 ^ 256) :
|
|||
|
|
(a : ZMod n) ^ k = ((powMod a k n : ℕ) : ZMod n) := by
|
|||
|
|
rw [powMod, powModAux_eq 256 a k n hk, ZMod.natCast_mod, Nat.cast_pow]
|
|||
|
|
|
|||
|
|
/- Positive direction — discharges the FERMAT condition (1) of the Lucas test.
|
|||
|
|
|
|||
|
|
MATH: k < 2^256 and powMod a k n = 1 ==> (a : ZMod n)^k = 1.
|
|||
|
|
The hypothesis `powMod a k n = 1` is a closed `Nat` equation the kernel
|
|||
|
|
checks by `decide`; this lemma lifts it to the `ZMod n` equation that
|
|||
|
|
`lucas_primality` consumes. -/
|
|||
|
|
theorem pow_eq_one_of_powMod (a k n : ℕ) (hk : k < 2 ^ 256) (h : powMod a k n = 1) :
|
|||
|
|
(a : ZMod n) ^ k = 1 := by
|
|||
|
|
rw [cast_pow_eq a k n hk, h, Nat.cast_one]
|
|||
|
|
|
|||
|
|
/- Negative direction — discharges the ORDER condition (2) of the Lucas test.
|
|||
|
|
|
|||
|
|
MATH: k < 2^256, 1 < n, powMod a k n ≠ 1, powMod a k n < n
|
|||
|
|
==> (a : ZMod n)^k ≠ 1.
|
|||
|
|
Subtlety: distinct naturals can become EQUAL in Z/n (they may differ by a
|
|||
|
|
multiple of n), so `powMod a k n ≠ 1` alone is not enough. The extra
|
|||
|
|
hypotheses pin both sides into the canonical range [0, n): the computed
|
|||
|
|
residue is < n (true by construction, but cheaper to re-`decide` than to
|
|||
|
|
prove generically) and 1 < n. Within that range the cast Nat → ZMod n is
|
|||
|
|
injective (`ZMod.natCast_eq_natCast_iff'` + `Nat.mod_eq_of_lt`), so
|
|||
|
|
inequality transfers.
|
|||
|
|
|
|||
|
|
WHY NEEDED: one application per prime factor q of n−1, with
|
|||
|
|
k = (n−1)/q — this is what forces the witness to have full order n−1. -/
|
|||
|
|
theorem pow_ne_one_of_powMod (a k n : ℕ) (hk : k < 2 ^ 256) (hn : 1 < n)
|
|||
|
|
(h1 : powMod a k n ≠ 1) (h2 : powMod a k n < n) :
|
|||
|
|
(a : ZMod n) ^ k ≠ 1 := by
|
|||
|
|
-- replace the ZMod power by the cast of the computed Nat residue
|
|||
|
|
rw [cast_pow_eq a k n hk]
|
|||
|
|
intro hcon
|
|||
|
|
-- equality of casts in ZMod n means equality of the residues mod n…
|
|||
|
|
rw [show (1 : ZMod n) = ((1 : ℕ) : ZMod n) by rw [Nat.cast_one],
|
|||
|
|
ZMod.natCast_eq_natCast_iff'] at hcon
|
|||
|
|
-- …and both residues are already < n, so they are equal as naturals
|
|||
|
|
rw [Nat.mod_eq_of_lt h2, Nat.mod_eq_of_lt hn] at hcon
|
|||
|
|
exact h1 hcon
|
|||
|
|
|
|||
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|||
|
|
-- The certificate chain, leaves first (factor tree in the file header).
|
|||
|
|
--
|
|||
|
|
-- Every theorem instantiates mathlib's
|
|||
|
|
-- lucas_primality (n) (g : ZMod n) (h1) (h2) : Nat.Prime n
|
|||
|
|
-- with a concrete witness g, discharging
|
|||
|
|
-- h1 : g^(n−1) = 1 in ZMod n via `pow_eq_one_of_powMod`
|
|||
|
|
-- (its two `by decide`s check: n−1 < 2^256, and the powMod equation)
|
|||
|
|
-- h2 : ∀ q prime, q ∣ n−1 → g^((n−1)/q) ≠ 1 via `pow_ne_one_of_powMod`
|
|||
|
|
-- (its four `by decide`s check: (n−1)/q < 2^256, 1 < n,
|
|||
|
|
-- powMod g ((n−1)/q) n ≠ 1, and powMod … < n).
|
|||
|
|
--
|
|||
|
|
-- For h2 the published factorization of n−1 is stated as a NESTED product
|
|||
|
|
-- 2^e * (f1 * (f2 * (…))) and verified by one `decide` (a single big-number
|
|||
|
|
-- multiplication). `rcases (Nat.Prime.dvd_mul hq).mp` then peels the factors
|
|||
|
|
-- left to right: a prime q dividing the product divides the head factor or
|
|||
|
|
-- the tail. Dividing the head pins q to a concrete prime via
|
|||
|
|
-- `Nat.prime_dvd_prime_iff_eq` ("a prime divides a prime iff they are
|
|||
|
|
-- equal"); for prime-power heads like 2^2 we first strip the exponent with
|
|||
|
|
-- `hq.dvd_of_dvd_pow`. Head factors small enough are certified prime by
|
|||
|
|
-- `norm_num`; large ones by the earlier theorems of this chain — that
|
|||
|
|
-- reference IS the recursion of the Pratt certificate.
|
|||
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
/- Leaf q7 of the factor tree: 8574133 is prime (needed for q5 below).
|
|||
|
|
Witness g = 2; 8574133 − 1 = 2^2 · 3 · 7 · 103 · 991, all `norm_num`-small.
|
|||
|
|
This first certificate is annotated line by line; the six that follow are
|
|||
|
|
structurally identical. -/
|
|||
|
|
theorem prime_8574133 : Nat.Prime 8574133 := by
|
|||
|
|
-- pick the witness g = 2 and split into the two Lucas obligations
|
|||
|
|
refine lucas_primality 8574133 ((2 : ℕ) : ZMod 8574133) ?_ ?_
|
|||
|
|
-- (1) Fermat: 2^(n−1) ≡ 1 (mod n) — one kernel powMod computation
|
|||
|
|
· exact pow_eq_one_of_powMod 2 (8574133 - 1) 8574133 (by decide) (by decide)
|
|||
|
|
-- (2) full order: any prime q | n−1 must leave 2^((n−1)/q) ≢ 1 (mod n)
|
|||
|
|
· intro q hq hqd
|
|||
|
|
-- kernel-verified factorization of n−1, nested for left-to-right peeling
|
|||
|
|
have hfac : (8574133 : ℕ) - 1 = 2 ^ 2 * (3 * (7 * (103 * (991)))) := by decide
|
|||
|
|
rw [hfac] at hqd
|
|||
|
|
-- q | 2^2 · rest: either q | 2^2 (then q = 2) or q divides the rest
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
|
|||
|
|
subst he
|
|||
|
|
-- 2^((n−1)/2) ≢ 1 (mod n), checked by the kernel
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((8574133 - 1) / 2) 8574133 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
-- q | 3 · rest: peel the factor 3
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 3 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((8574133 - 1) / 3) 8574133 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
-- peel the factor 7
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 7 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((8574133 - 1) / 7) 8574133 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
-- peel the factor 103
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 103 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((8574133 - 1) / 103) 8574133 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
-- only the last factor 991 remains
|
|||
|
|
have he : q = 991 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp hqd
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((8574133 - 1) / 991) 8574133 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
|
|||
|
|
/- Leaf q6 of the factor tree: 2773320623 is prime (needed for q4 below).
|
|||
|
|
Witness g = 5; 2773320623 − 1 = 2 · 2437 · 569003, all `norm_num`-small.
|
|||
|
|
(g = 2 would fail here: 2 is a quadratic residue mod this prime, so
|
|||
|
|
2^((n−1)/2) ≡ 1 and the q = 2 order check breaks; hence the witness 5.) -/
|
|||
|
|
theorem prime_2773320623 : Nat.Prime 2773320623 := by
|
|||
|
|
refine lucas_primality 2773320623 ((5 : ℕ) : ZMod 2773320623) ?_ ?_
|
|||
|
|
-- Fermat condition, then one order check per prime factor of n−1
|
|||
|
|
· exact pow_eq_one_of_powMod 5 (2773320623 - 1) 2773320623 (by decide) (by decide)
|
|||
|
|
· intro q hq hqd
|
|||
|
|
have hfac : (2773320623 : ℕ) - 1 = 2 * (2437 * (569003)) := by decide
|
|||
|
|
rw [hfac] at hqd
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 5 ((2773320623 - 1) / 2) 2773320623 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 2437 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 5 ((2773320623 - 1) / 2437) 2773320623 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
have he : q = 569003 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp hqd
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 5 ((2773320623 - 1) / 569003) 2773320623 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
|
|||
|
|
/- Node q4 of the factor tree: 72106336199 is prime (needed for q3 below).
|
|||
|
|
Witness g = 7; 72106336199 − 1 = 2 · 13 · 2773320623.
|
|||
|
|
First RECURSIVE step of the Pratt certificate: the large factor q6 is
|
|||
|
|
certified by `prime_2773320623` above instead of `norm_num`. -/
|
|||
|
|
theorem prime_72106336199 : Nat.Prime 72106336199 := by
|
|||
|
|
refine lucas_primality 72106336199 ((7 : ℕ) : ZMod 72106336199) ?_ ?_
|
|||
|
|
· exact pow_eq_one_of_powMod 7 (72106336199 - 1) 72106336199 (by decide) (by decide)
|
|||
|
|
· intro q hq hqd
|
|||
|
|
have hfac : (72106336199 : ℕ) - 1 = 2 * (13 * (2773320623)) := by decide
|
|||
|
|
rw [hfac] at hqd
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 7 ((72106336199 - 1) / 2) 72106336199 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 13 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 7 ((72106336199 - 1) / 13) 72106336199 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
-- last factor: q6 = 2773320623, prime by the recursive certificate above
|
|||
|
|
have he : q = 2773320623 := (Nat.prime_dvd_prime_iff_eq hq prime_2773320623).mp hqd
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 7 ((72106336199 - 1) / 2773320623) 72106336199 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
|
|||
|
|
/- Node q5 of the factor tree: 1919519569386763 is prime (needed for q3 below).
|
|||
|
|
Witness g = 2; q5 − 1 = 2 · 3 · 7 · 19 · 47^2 · 127 · 8574133.
|
|||
|
|
Note the prime-power factor 47^2: only ONE order check is needed per
|
|||
|
|
distinct prime (the test divides n−1 by q once), so the branch for 47
|
|||
|
|
strips the square with `hq.dvd_of_dvd_pow` first. The large factor
|
|||
|
|
q7 = 8574133 is certified by `prime_8574133`. -/
|
|||
|
|
theorem prime_1919519569386763 : Nat.Prime 1919519569386763 := by
|
|||
|
|
refine lucas_primality 1919519569386763 ((2 : ℕ) : ZMod 1919519569386763) ?_ ?_
|
|||
|
|
· exact pow_eq_one_of_powMod 2 (1919519569386763 - 1) 1919519569386763 (by decide) (by decide)
|
|||
|
|
· intro q hq hqd
|
|||
|
|
have hfac : (1919519569386763 : ℕ) - 1 = 2 * (3 * (7 * (19 * (47 ^ 2 * (127 * (8574133)))))) := by decide
|
|||
|
|
rw [hfac] at hqd
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((1919519569386763 - 1) / 2) 1919519569386763 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 3 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((1919519569386763 - 1) / 3) 1919519569386763 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 7 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((1919519569386763 - 1) / 7) 1919519569386763 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 19 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((1919519569386763 - 1) / 19) 1919519569386763 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 47 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((1919519569386763 - 1) / 47) 1919519569386763 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 127 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((1919519569386763 - 1) / 127) 1919519569386763 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
-- last factor: q7 = 8574133, prime by the recursive certificate above
|
|||
|
|
have he : q = 8574133 := (Nat.prime_dvd_prime_iff_eq hq prime_8574133).mp hqd
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((1919519569386763 - 1) / 8574133) 1919519569386763 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
|
|||
|
|
/- Leaf q2 of the factor tree: 31757755568855353 is prime (needed for q1).
|
|||
|
|
Witness g = 10; q2 − 1 = 2^3 · 3 · 31 · 107 · 223 · 4153 · 430751,
|
|||
|
|
all `norm_num`-small — no recursion needed for this node. -/
|
|||
|
|
theorem prime_31757755568855353 : Nat.Prime 31757755568855353 := by
|
|||
|
|
refine lucas_primality 31757755568855353 ((10 : ℕ) : ZMod 31757755568855353) ?_ ?_
|
|||
|
|
· exact pow_eq_one_of_powMod 10 (31757755568855353 - 1) 31757755568855353 (by decide) (by decide)
|
|||
|
|
· intro q hq hqd
|
|||
|
|
have hfac : (31757755568855353 : ℕ) - 1 = 2 ^ 3 * (3 * (31 * (107 * (223 * (4153 * (430751)))))) := by decide
|
|||
|
|
rw [hfac] at hqd
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 10 ((31757755568855353 - 1) / 2) 31757755568855353 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 3 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 10 ((31757755568855353 - 1) / 3) 31757755568855353 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 31 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 10 ((31757755568855353 - 1) / 31) 31757755568855353 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 107 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 10 ((31757755568855353 - 1) / 107) 31757755568855353 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 223 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 10 ((31757755568855353 - 1) / 223) 31757755568855353 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 4153 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 10 ((31757755568855353 - 1) / 4153) 31757755568855353 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
have he : q = 430751 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp hqd
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 10 ((31757755568855353 - 1) / 430751) 31757755568855353 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
|
|||
|
|
/- Node q3 of the factor tree: the 116-bit 75445702479781427272750846543864801
|
|||
|
|
is prime (needed for q1). Witness g = 7;
|
|||
|
|
q3 − 1 = 2^5 · 3^2 · 5^2 · 75707 · q4 · q5 with the two large factors
|
|||
|
|
q4 = 72106336199 and q5 = 1919519569386763 certified recursively above. -/
|
|||
|
|
theorem prime_75445702479781427272750846543864801 : Nat.Prime 75445702479781427272750846543864801 := by
|
|||
|
|
refine lucas_primality 75445702479781427272750846543864801 ((7 : ℕ) : ZMod 75445702479781427272750846543864801) ?_ ?_
|
|||
|
|
· exact pow_eq_one_of_powMod 7 (75445702479781427272750846543864801 - 1) 75445702479781427272750846543864801 (by decide) (by decide)
|
|||
|
|
· intro q hq hqd
|
|||
|
|
have hfac : (75445702479781427272750846543864801 : ℕ) - 1 = 2 ^ 5 * (3 ^ 2 * (5 ^ 2 * (75707 * (72106336199 * (1919519569386763))))) := by decide
|
|||
|
|
rw [hfac] at hqd
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 7 ((75445702479781427272750846543864801 - 1) / 2) 75445702479781427272750846543864801 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 3 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 7 ((75445702479781427272750846543864801 - 1) / 3) 75445702479781427272750846543864801 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 5 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 7 ((75445702479781427272750846543864801 - 1) / 5) 75445702479781427272750846543864801 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 75707 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 7 ((75445702479781427272750846543864801 - 1) / 75707) 75445702479781427272750846543864801 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
-- factor q4 = 72106336199: prime by the recursive certificate above
|
|||
|
|
· have he : q = 72106336199 := (Nat.prime_dvd_prime_iff_eq hq prime_72106336199).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 7 ((75445702479781427272750846543864801 - 1) / 72106336199) 75445702479781427272750846543864801 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
-- last factor q5 = 1919519569386763: prime by the recursive certificate
|
|||
|
|
have he : q = 1919519569386763 := (Nat.prime_dvd_prime_iff_eq hq prime_1919519569386763).mp hqd
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 7 ((75445702479781427272750846543864801 - 1) / 1919519569386763) 75445702479781427272750846543864801 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
|
|||
|
|
/- Node q1 of the factor tree: the 236-bit cofactor of p − 1 is prime.
|
|||
|
|
Witness g = 2;
|
|||
|
|
q1 − 1 = 2 · 3 · 353 · 57467 · 132049 · 1923133 · q2 · q3,
|
|||
|
|
with q2 = 31757755568855353 and q3 = 75445702479781427272750846543864801
|
|||
|
|
certified recursively above. This is the last node below the root. -/
|
|||
|
|
theorem prime_74058212732561358302231226437062788676166966415465897661863160754340907 : Nat.Prime 74058212732561358302231226437062788676166966415465897661863160754340907 := by
|
|||
|
|
refine lucas_primality 74058212732561358302231226437062788676166966415465897661863160754340907 ((2 : ℕ) : ZMod 74058212732561358302231226437062788676166966415465897661863160754340907) ?_ ?_
|
|||
|
|
· exact pow_eq_one_of_powMod 2 (74058212732561358302231226437062788676166966415465897661863160754340907 - 1) 74058212732561358302231226437062788676166966415465897661863160754340907 (by decide) (by decide)
|
|||
|
|
· intro q hq hqd
|
|||
|
|
have hfac : (74058212732561358302231226437062788676166966415465897661863160754340907 : ℕ) - 1 = 2 * (3 * (353 * (57467 * (132049 * (1923133 * (31757755568855353 * (75445702479781427272750846543864801))))))) := by decide
|
|||
|
|
rw [hfac] at hqd
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((74058212732561358302231226437062788676166966415465897661863160754340907 - 1) / 2) 74058212732561358302231226437062788676166966415465897661863160754340907 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 3 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((74058212732561358302231226437062788676166966415465897661863160754340907 - 1) / 3) 74058212732561358302231226437062788676166966415465897661863160754340907 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 353 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((74058212732561358302231226437062788676166966415465897661863160754340907 - 1) / 353) 74058212732561358302231226437062788676166966415465897661863160754340907 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 57467 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((74058212732561358302231226437062788676166966415465897661863160754340907 - 1) / 57467) 74058212732561358302231226437062788676166966415465897661863160754340907 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 132049 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((74058212732561358302231226437062788676166966415465897661863160754340907 - 1) / 132049) 74058212732561358302231226437062788676166966415465897661863160754340907 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 1923133 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((74058212732561358302231226437062788676166966415465897661863160754340907 - 1) / 1923133) 74058212732561358302231226437062788676166966415465897661863160754340907 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
-- factor q2: prime by the recursive certificate above
|
|||
|
|
· have he : q = 31757755568855353 := (Nat.prime_dvd_prime_iff_eq hq prime_31757755568855353).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((74058212732561358302231226437062788676166966415465897661863160754340907 - 1) / 31757755568855353) 74058212732561358302231226437062788676166966415465897661863160754340907 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
-- last factor q3: prime by the recursive certificate above
|
|||
|
|
have he : q = 75445702479781427272750846543864801 := (Nat.prime_dvd_prime_iff_eq hq prime_75445702479781427272750846543864801).mp hqd
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((74058212732561358302231226437062788676166966415465897661863160754340907 - 1) / 75445702479781427272750846543864801) 74058212732561358302231226437062788676166966415465897661863160754340907 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
|
|||
|
|
/- ROOT of the factor tree: p = 2^255 − 19 itself, written out in decimal
|
|||
|
|
(57896044618658097711785492504343953926634992332820282019728792003956564819949).
|
|||
|
|
Witness g = 2 (2 is in fact a primitive root mod p);
|
|||
|
|
p − 1 = 2^2 · 3 · 65147 · q1, with the 236-bit q1 certified just above.
|
|||
|
|
Each `powMod` check here exponentiates with a ~255-bit exponent modulo the
|
|||
|
|
255-bit p — still milliseconds thanks to GMP-backed kernel `Nat` arithmetic. -/
|
|||
|
|
theorem prime_57896044618658097711785492504343953926634992332820282019728792003956564819949 : Nat.Prime 57896044618658097711785492504343953926634992332820282019728792003956564819949 := by
|
|||
|
|
refine lucas_primality 57896044618658097711785492504343953926634992332820282019728792003956564819949 ((2 : ℕ) : ZMod 57896044618658097711785492504343953926634992332820282019728792003956564819949) ?_ ?_
|
|||
|
|
· exact pow_eq_one_of_powMod 2 (57896044618658097711785492504343953926634992332820282019728792003956564819949 - 1) 57896044618658097711785492504343953926634992332820282019728792003956564819949 (by decide) (by decide)
|
|||
|
|
· intro q hq hqd
|
|||
|
|
have hfac : (57896044618658097711785492504343953926634992332820282019728792003956564819949 : ℕ) - 1 = 2 ^ 2 * (3 * (65147 * (74058212732561358302231226437062788676166966415465897661863160754340907))) := by decide
|
|||
|
|
rw [hfac] at hqd
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 2 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp (hq.dvd_of_dvd_pow h)
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((57896044618658097711785492504343953926634992332820282019728792003956564819949 - 1) / 2) 57896044618658097711785492504343953926634992332820282019728792003956564819949 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 3 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((57896044618658097711785492504343953926634992332820282019728792003956564819949 - 1) / 3) 57896044618658097711785492504343953926634992332820282019728792003956564819949 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
rcases (Nat.Prime.dvd_mul hq).mp hqd with h | hqd
|
|||
|
|
· have he : q = 65147 := (Nat.prime_dvd_prime_iff_eq hq (by norm_num)).mp h
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((57896044618658097711785492504343953926634992332820282019728792003956564819949 - 1) / 65147) 57896044618658097711785492504343953926634992332820282019728792003956564819949 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
-- last factor q1: prime by the recursive certificate above
|
|||
|
|
have he : q = 74058212732561358302231226437062788676166966415465897661863160754340907 := (Nat.prime_dvd_prime_iff_eq hq prime_74058212732561358302231226437062788676166966415465897661863160754340907).mp hqd
|
|||
|
|
subst he
|
|||
|
|
exact pow_ne_one_of_powMod 2 ((57896044618658097711785492504343953926634992332820282019728792003956564819949 - 1) / 74058212732561358302231226437062788676166966415465897661863160754340907) 57896044618658097711785492504343953926634992332820282019728792003956564819949 (by decide) (by decide) (by decide) (by decide)
|
|||
|
|
|
|||
|
|
end P25519
|
|||
|
|
|
|||
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|||
|
|
-- Exported result
|
|||
|
|
-- ─────────────────────────────────────────────────────────────────────────────
|
|||
|
|
|
|||
|
|
/-- The Curve25519 field prime `2 ^ 255 - 19` is prime.
|
|||
|
|
|
|||
|
|
MATH (ASCII): Nat.Prime (2^255 - 19)
|
|||
|
|
LaTeX: $2^{255} - 19$ is prime.
|
|||
|
|
|
|||
|
|
This is the only theorem of this file used downstream: Proofs/Field.lean turns
|
|||
|
|
it into `P_prime : Nat.Prime P` (where `P` abbreviates the same number) and the
|
|||
|
|
`Fact (Nat.Prime P)` instance, which activates mathlib's `Field (ZMod P)` —
|
|||
|
|
the target structure of the main theorem `fieldImplementation`
|
|||
|
|
(Proofs/FieldMain.lean) — and feeds Fermat's little theorem to the inverse
|
|||
|
|
spec (Proofs/InvertSpec.lean), mirroring the comment on
|
|||
|
|
`FieldElement::invert` in curve25519/solana-ed25519/src/field.rs:239-248. -/
|
|||
|
|
theorem p25519_prime : Nat.Prime (2 ^ 255 - 19) := by
|
|||
|
|
-- rewrite 2^255 − 19 into the decimal literal the root certificate is about
|
|||
|
|
have h : (2 : ℕ) ^ 255 - 19 = 57896044618658097711785492504343953926634992332820282019728792003956564819949 := by decide
|
|||
|
|
rw [h]
|
|||
|
|
exact P25519.prime_57896044618658097711785492504343953926634992332820282019728792003956564819949
|