Theory FIPS186_4_Curves
theory FIPS186_4_Curves
imports "Efficient_SEC1"
begin
text ‹In FIPS 186-4, NIST defines several recommended curves for government use. In this theory,
we define the NIST recommended curves over prime fields, that is, all the curves that are labelled
with "P-" Note that all these curves have cofactor h=1 and coefficient a = p-3.
https://csrc.nist.gov/Projects/Elliptic-Curve-Cryptography
https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
Below you will find the parameters given by NIST for the "P-" curves. Then we prove that these
parameters meet the definition of a valid elliptic curve. Of course, to be a valid elliptic
curve with h=1, we must know that p and n are prime and also that the number of (integer) points
on the curve is n (=n*h). These three things we do not attempt to prove; instead, we take them
as given as axioms. All other facts about valid elliptic curves can be and are checked below.
Note that FIPS 186-4 is being replaced by FIPS 186-5. The curve parameters listed here appear
unchanged in the new version of the standard.›
section ‹P-192›
subsection ‹Parameters›
definition P192_p :: nat where
"P192_p = 6277101735386680763835789423207666416083908700390324961279"
definition P192_n :: nat where
"P192_n = 6277101735386680763835789423176059013767194773182842284081"
definition P192_SEED :: nat where
"P192_SEED = 0x3045ae6fc8422f64ed579528d38120eae12196d5"
definition P192_c :: nat where
"P192_c = 0x3099d2bbbfcb2538542dcd5fb078b6ef5f3d6fe2c745de65"
definition P192_a :: nat where
"P192_a = P192_p - 3"
definition P192_b :: nat where
"P192_b = 0x64210519e59c80e70fa7e9ab72243049feb8deecc146b9b1"
definition P192_Gx :: nat where
"P192_Gx = 0x188da80eb03090f67cbf20eb43a18800f4ff0afd82ff1012"
definition P192_Gy :: nat where
"P192_Gy = 0x07192b95ffc8da78631011ed6b24cdd573f977a11e794811"
definition P192_G :: "int point" where
"P192_G = Point (int P192_Gx) (int P192_Gy)"
definition P192_prG :: "int ppoint" where
"P192_prG = (int P192_Gx, int P192_Gy, 1)"
definition P192_h :: nat where
"P192_h = 1"
definition P192_t :: nat where
"P192_t = 80"
subsection ‹Parameter Checks›
text‹We can't easily check that n and p are prime, but there are many conditions on the parameters
of an elliptic curve to be considered a valid curve. We verify now the things that we can check.›
text‹We are just going to assume that p is prime.›
axiomatization where P192_p_prime: "prime P192_p"
text‹But we can easily see that p is an odd prime.›
lemma P192_p_gr2: "2 < P192_p" by eval
text‹We are just going to assume that n is prime.›
axiomatization where P192_n_prime: "prime P192_n"
text ‹Check (∀B∈{1..99}. (p^B mod n ≠ 1)).›
lemma P192_checkPmodN: "∀i∈{1..99}. (P192_p^i mod P192_n ≠ 1)"
proof -
have 1: "list_all (%i. P192_p^i mod P192_n ≠ 1) [1..<100]" by eval
have 2: "∀i ∈ set [1..<100]. (P192_p^i mod P192_n ≠ 1)"
by (metis (mono_tags, lifting) 1 Ball_set)
have 3: "set [1..<100] = {1::nat..99}" by fastforce
show ?thesis using 2 3 by blast
qed
text‹Check (a ∈ carrier R) ∧ (b ∈ carrier R) ∧ (nonsingular a b)›
lemma P192_checkA: "P192_a < P192_p" by eval
lemma P192_checkB: "P192_b < P192_p" by eval
lemma P192_checkNonsingular: "(4*P192_a^3 + 27*P192_b^2) mod P192_p ≠ 0"
by eval
text ‹Check (on_curve a b G) ∧ (G ≠ Infinity) ∧ (point_mult a n G = Infinity)›
lemma P192_checkGnotInf: "P192_G ≠ Infinity"
by eval
lemma P192_checkGoncurve: "mon_curve P192_p P192_a P192_b P192_G"
by eval
lemma P192_checkGord:
"mmake_affine P192_p (fast_ppoint_mult P192_p P192_a P192_n P192_prG) = Infinity"
by eval
text ‹Check the cofactor h and the security level t.›
lemma P192_checkT: "P192_t ∈ {80, 112, 128, 192, 256}"
by eval
lemma P192_checkHT: "P192_h ≤ 2^(P192_t div 8)"
by eval
lemma P192_checkNHnotP: "P192_n * P192_h ≠ P192_p"
by eval
lemma P192_checkHnot0: "0 < P192_h"
by eval
text ‹Check ‹h = ⌊((sqrt p + 1)^2) div n⌋›. This is slightly more involved than the above checks.›
lemma P192_checkH1: "(P192_h*P192_n - P192_p - 1)^2 ≤ 4*P192_p" by eval
lemma P192_checkH2: "4*P192_p < ((P192_h+1)*P192_n - P192_p - 1)^2" by eval
lemma P192_checkH: "P192_h = ⌊((sqrt P192_p + 1)^2) div P192_n⌋"
proof -
have p1: "((sqrt P192_p) + 1)^2 = P192_p + 2*(sqrt P192_p) + 1"
by (simp add: power2_sum)
have n1: "0 < P192_n" by eval
have l1: "P192_h*P192_n - P192_p - 1 ≤ 2*(sqrt P192_p)"
by (metis (mono_tags, opaque_lifting) P192_checkH1 real_le_rsqrt of_nat_le_iff of_nat_mult
of_nat_numeral of_nat_power real_sqrt_four real_sqrt_mult)
have l2: "P192_h*P192_n ≤ P192_p + 2*(sqrt P192_p) + 1"
using l1 by linarith
have l3: "P192_h*P192_n ≤ ((sqrt P192_p) + 1)^2"
using l2 p1 by presburger
have l4: "P192_h ≤ (((sqrt P192_p) + 1)^2) div P192_n"
using l3 pos_le_divide_eq n1 by force
have g1: "2*(sqrt P192_p) < (P192_h+1)*P192_n - P192_p - 1"
by (metis (mono_tags, opaque_lifting) P192_checkH2 real_less_lsqrt of_nat_mult of_nat_less_iff
of_nat_numeral of_nat_power real_sqrt_four real_sqrt_mult of_nat_0_le_iff)
have g2: "P192_p + 2*(sqrt P192_p) + 1 < (P192_h+1)*P192_n"
by (smt (verit, ccfv_SIG) g1 P192_p_gr2 add_diff_inverse_nat cring_class.of_nat_add of_nat_1
less_diff_conv less_imp_of_nat_less nat_1_add_1 of_nat_less_imp_less real_sqrt_ge_one)
have g3: "((sqrt P192_p) + 1)^2 < (P192_h+1)*P192_n"
using g2 p1 by presburger
have g4: "(((sqrt P192_p) + 1)^2) div P192_n < (P192_h+1)"
by (metis g3 n1 pos_divide_less_eq of_nat_0_less_iff of_nat_mult)
show ?thesis using l4 g4 by linarith
qed
subsection ‹Interpretations›
text ‹Because p is (assumed to be) prime and greater than 2, we can interpret the
residues_prime_gr2 locale.›
lemma P192_residues_prime_gt2: "residues_prime_gt2 P192_p"
using P192_p_prime P192_p_gr2 residues_prime_gt2_def residues_prime.intro
residues_prime_gt2_axioms.intro by blast
definition P192_R :: "int ring" where
"P192_R = residue_ring (int P192_p)"