verifying-crypto-with-lean/solutions/Ch07.lean
saymrwulf 45048d4898 Verifying Cryptography with Lean 4: complete 12-chapter curriculum
- 53-page LaTeX/TikZ book (main.pdf + full sources): from zero background
  to reading the real Ed25519/Pasta verification projects
- runnable exercises with sorry-holes + complete solutions for chapters
  2-7, 9, 12; every solution file compiles clean (zero errors, no sorry)
  against Lean v4.30.0-rc2 + Mathlib 5450b53e
- lake project pinned to the same toolchain/Mathlib the solutions were
  verified with; students fetch the Mathlib cache, never build it
- honesty ledger in README: what was machine-checked and how

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 09:44:40 +02:00

50 lines
1.7 KiB
Text

/- Chapter 7 — solutions. -/
import Mathlib.Data.ZMod.Basic
import Mathlib.Tactic.NormNum.Prime
namespace Ch07
-- 7.A: small enough for kernel trial division.
example : Nat.Prime 97 := by
decide
-- 7.B: norm_num's certificate route — instant where decide crawls.
example : Nat.Prime 65537 := by
norm_num
-- 7.C: certificate or nothing at ten digits. One wrinkle worth knowing:
-- norm_num's prime extension wants a LITERAL, so first change the goal to
-- the (definitionally equal) evaluated numeral with `show`.
example : Nat.Prime (2^31 - 1) := by
show Nat.Prime 2147483647
norm_num
/- 7.D: Pratt witness for p = 13, w = 2. Hand computation:
2^12 = 4096 = 315*13 + 1 → 1 ✓ (first condition)
2^6 = 64 = 4*13 + 12 → 12 ✓ (≠ 1, q = 2)
2^4 = 16 = 13 + 3 → 3 ✓ (≠ 1, q = 3) -/
#eval (2:ZMod 13)^12 -- 1
#eval (2:ZMod 13)^6 -- 12 (not 1)
#eval (2:ZMod 13)^4 -- 3 (not 1)
-- 7.E: square-and-multiply.
def powModAux : Nat → Nat → Nat → Nat → Nat → Nat
| 0, _, _, _, acc => acc
| fuel+1, b, e, m, acc =>
if e = 0 then acc
else powModAux fuel (b*b % m) (e/2) m (if e % 2 = 1 then acc*b % m else acc)
def powMod (b e m : Nat) : Nat :=
if m ≤ 1 then 0 else powModAux 300 (b % m) e m 1
#eval powMod 2 12 13 -- 1
#eval powMod 3 4 7 -- 4
/- Fermat's little theorem in action at 77 digits: the answer is 1, in
milliseconds — this is why certificate CHECKING is cheap. (One node of
the witness tree; the full kernel-checked certificate for the Pallas
modulus lives in pasta-pallas-verified.) -/
def p : Nat := 2^255 - 19
#eval powMod 2 (p - 1) p -- 1
end Ch07