Theory Primitives

theory Primitives

imports Pairing  
begin

section ‹Mathematical Primitives›

text ‹We define the mathematical primitives used throughout our formalization as well as some
useful lemmas (mostly identities).›
locale math_primitives = pairing Gp  GT p e
  for Gp :: "('a, 'b) cyclic_group_scheme" (structure)
  and GT:: "('c, 'd) cyclic_group_scheme"  (structure)
  and p::int
  and e::"'a  'a  'c"
+ 
fixes "type_q" :: "('q :: prime_card) itself"
and max_deg::nat
assumes
p_gr_two: "p > 2" and
d_pos: "max_deg > 0" and
CARD_q: "int (CARD('q)) = p" and
d_l_p: "max_deg < p"
begin

abbreviation pow_mod_ring (infixr "^ı" 75)
  where "x ^ı y   x [^]ı (to_int_mod_ring (y::'q mod_ring))"

abbreviation div_in_grp (infixr "÷ı" 70)
  where "x ÷ı y  x ı invı y"

subsubsection ‹mod\_ring operations on pow of Gp›

lemma carrier_pow_mod_order_Gp: 
  assumes "g  carrier Gp"
  shows "g [^]Gpx = g [^]Gp(x mod p)"
proof -
  have "p=(order Gp)" by (simp add: CARD_Gp)
  also have "g [^]Gpx = g [^]Gp(x mod order Gp)"
  proof -
    have "g [^]Gpx  carrier Gp" by (simp add: assms)
    let ?d = "x div (order Gp)"
    have "g [^]Gpx = g [^]Gp(?d * order Gp + x mod order Gp)" 
      using div_mult_mod_eq by presburger
    also have "= g [^]Gp(?d * order Gp) Gpg [^]Gp(x mod order Gp)"
      using Gp.int_pow_mult assms by blast
    also have "=𝟭GpGpg [^]Gp(x mod order Gp)"
      by (metis Gp.int_pow_closed Gp.int_pow_pow Gp.pow_order_eq_1 assms int_pow_int)
    finally show "g [^]Gpx = g [^]Gp(x mod order Gp)"
      using assms by fastforce
  qed
  finally show "g [^]Gpx = g [^]Gp(x mod p)" .
qed

lemma pow_mod_order_Gp: "gGp[^]Gpx = gGp[^]Gp(x mod p)"
  using carrier_pow_mod_order_Gp by blast

lemma mod_ring_pow_mult_inv_Gp[symmetric]:" (gGp[^]Gp(to_int_mod_ring (a::'q mod_ring))) GpinvGp(gGp[^]Gp(to_int_mod_ring b)) 
  =  gGp[^]Gp(to_int_mod_ring (a-b))"
proof -
  have "(gGp[^]Gp(to_int_mod_ring (a::'q mod_ring))) GpinvGp(gGp[^]Gp(to_int_mod_ring b)) 
        = (gGp[^]Gp(to_int_mod_ring (a::'q mod_ring))) Gp(gGp[^]Gp(- to_int_mod_ring b))"
    by (simp add: Gp.int_pow_neg)
  also have "=(gGp[^]Gp((to_int_mod_ring a + -to_int_mod_ring b) mod CARD ('q)))"
    using pow_mod_order_Gp CARD_q Gp.generator_closed Gp.int_pow_mult by presburger
  also have "=(gGp[^]Gp((to_int_mod_ring a - to_int_mod_ring b) mod CARD ('q)))"
    by fastforce
  also have "=  gGp[^]Gpto_int_mod_ring (a - b)"
    by (simp add: minus_mod_ring.rep_eq to_int_mod_ring.rep_eq)
  finally show "gGp[^]Gpto_int_mod_ring a GpinvGp(gGp[^]Gpto_int_mod_ring b) = gGp[^]Gpto_int_mod_ring (a - b)" .
qed

lemma mod_ring_pow_mult_Gp[symmetric]:" (gGp[^]Gp(to_int_mod_ring (a::'q mod_ring))) Gp(gGp[^]Gp(to_int_mod_ring b)) 
  =  gGp[^]Gp(to_int_mod_ring (a+b))"
proof -
  have "gGp[^]Gpto_int_mod_ring a GpgGp[^]Gpto_int_mod_ring b =  gGp[^]Gp(to_int_mod_ring a + to_int_mod_ring b)"
    by (simp add: Gp.int_pow_mult)
  also have "=  gGp[^]Gp((to_int_mod_ring a + to_int_mod_ring b) mod (CARD ('q)))" 
    using pow_mod_order_Gp CARD_q by blast
  also have "=  gGp[^]Gpto_int_mod_ring (a + b)"
    by (simp add: plus_mod_ring.rep_eq to_int_mod_ring.rep_eq)
  finally show "gGp[^]Gpto_int_mod_ring a GpgGp[^]Gpto_int_mod_ring b = gGp[^]Gpto_int_mod_ring (a + b)" .
qed

lemma mod_ring_pow_pow_Gp[symmetric]: "(gGp[^]Gp(to_int_mod_ring (a::'q mod_ring))) [^]Gp(to_int_mod_ring (b::'q mod_ring)) 
                       = gGp[^]Gp(to_int_mod_ring (a*b::'q mod_ring))"
proof -
  have "(gGp[^]Gpto_int_mod_ring a) [^]Gpto_int_mod_ring b = (gGp[^]Gp(to_int_mod_ring a * to_int_mod_ring b))"
    using Gp.int_pow_pow by auto
  also have " = (gGp[^]Gp((to_int_mod_ring a * to_int_mod_ring b) mod CARD ('q)))"
    using CARD_q pow_mod_order_Gp by blast
  also have "=  gGp[^]Gpto_int_mod_ring (a * b)"
    by (simp add: times_mod_ring.rep_eq to_int_mod_ring.rep_eq)
  finally show "(gGp[^]Gpto_int_mod_ring a) [^]Gpto_int_mod_ring b 
               = gGp[^]Gpto_int_mod_ring (a * b)" .
qed

lemma to_int_mod_ring_ge_0: "to_int_mod_ring x  0" 
  using range_to_int_mod_ring by fastforce

lemma pow_on_eq_card: "(gGp^Gpx = gGp^Gpy) = (x=y)"
proof 
  assume assm: "g ^Gpx = g ^Gpy"
  then have "gGp[^]Gpto_int_mod_ring x = gGp[^]Gpto_int_mod_ring y"
    using assm by blast
  then have "gGp[^]Gpnat (to_int_mod_ring x) = gGp[^]Gpnat (to_int_mod_ring y)" 
    using to_int_mod_ring_ge_0[of "x"] to_int_mod_ring_ge_0[of "y"] by fastforce
  then have "[nat (to_int_mod_ring x) = nat (to_int_mod_ring y)] (mod order Gp)"
    using Gp.pow_generator_eq_iff_cong Gp.finite_carrier by fast
  then have "[to_int_mod_ring x = to_int_mod_ring y] (mod order Gp)" 
    using to_int_mod_ring_ge_0[of "x"] to_int_mod_ring_ge_0[of "y"]
    by (metis cong_int_iff int_nat_eq)
  then have "[to_int_mod_ring x = to_int_mod_ring y] (mod p)" 
    using CARD_Gp by fast
  then have "to_int_mod_ring x = to_int_mod_ring y"
    by (metis Rep_mod_ring_mod to_int_mod_ring.rep_eq unique_euclidean_semiring_class.cong_def 
        CARD_q)
  then show "x = y" by force
next 
  assume "x = y"
  then show "g ^Gpx = g ^Gpy" by fast
qed

lemma g_pow_to_int_mod_ring_of_int_mod_ring: " g ^Gpof_int_mod_ring x =  g [^] x"
proof -
  have "g ^Gpof_int_mod_ring x =  g [^] (x mod p)"
    by (simp add: CARD_q of_int_mod_ring.rep_eq to_int_mod_ring.rep_eq)
  also have "= g [^] x" using CARD_Gp Gp.pow_generator_mod_int by presburger
  finally show ?thesis .
qed

lemma g_pow_to_int_mod_ring_of_int_mod_ring_pow_t: "g ^Gpof_int_mod_ring x ^ (t::nat) =  g [^] x ^ t"
  by (metis g_pow_to_int_mod_ring_of_int_mod_ring of_int_of_int_mod_ring of_int_power)

lemma carrier_inj_on_multc: "c  0  inj_on (λx. x ^Gpc) (carrier Gp)"
proof 
  fix x y
  assume c: "c  0"
  assume x: " x  carrier Gp"
  assume y: " y  carrier Gp"
  assume asm: "x ^ c = y ^ c"
  obtain x_pow where x_pow: "g ^Gpx_pow = x"
    using x 
    by (metis Gp.generatorE g_pow_to_int_mod_ring_of_int_mod_ring int_pow_int)
  obtain y_pow where y_pow: "g ^Gpy_pow = y"
    using y 
    by (metis Gp.generatorE g_pow_to_int_mod_ring_of_int_mod_ring int_pow_int)
  then have "(g ^Gpx_pow) ^Gpc = (g ^Gpy_pow) ^Gpc"
    using asm x_pow y_pow by blast
  then have "(g ^Gp(x_pow*c))= (g ^Gp(y_pow*c))"
    using mod_ring_pow_pow_Gp by presburger
  then have "x_pow * c = y_pow*c"
    using pow_on_eq_card by force
  then have "x_pow = y_pow"
    using c by simp
  then show "x=y"
    using x_pow y_pow by blast
qed

subsubsection‹mod\_ring operations on pow of GT›

lemma pow_mod_order_GT: "g  carrier GT  g [^]GTx = g [^]GT(x mod p)" 
proof -
  assume asmpt: "g  carrier GT"
  have "p=(order GT)" by (simp add: CARD_GT)
  also have "g[^]GTx = g [^]GT(x mod order GT)"
  proof -
    have "g [^]GTx  carrier GT" using asmpt by simp
    let ?d = "x div (order GT)"
    have "g [^]GTx = g [^]GT(?d * order GT + x mod order GT)" 
      using div_mult_mod_eq by presburger
    also have "=g [^]GT(?d * order GT) GTg [^]GT(x mod order GT)"
      using GT.int_pow_mult asmpt by fast
    also have "=𝟭GTGTg [^]GT(x mod order GT)"
      by (metis GT.int_pow_one GT.int_pow_pow GT.pow_order_eq_1 int_pow_int mult.commute asmpt)
    finally show "g [^]GTx = g [^]GT(x mod order GT)"
      using asmpt by fastforce
  qed
  finally show "g [^]GTx = g [^]GT(x mod p)" .
qed


lemma mod_ring_pow_mult_GT[symmetric]:" x  carrier GT  (x [^]GT(to_int_mod_ring (a::'q mod_ring))) GT(x [^]GT(to_int_mod_ring b)) 
  =  x [^]GT(to_int_mod_ring (a+b))"
proof -
  assume asmpt: "x  carrier GT"
  have "x [^]GTto_int_mod_ring a GTx [^]GTto_int_mod_ring b =  x [^]GT(to_int_mod_ring a + to_int_mod_ring b)"
    by (simp add: GT.int_pow_mult asmpt)
  also have "=  x [^]GT((to_int_mod_ring a + to_int_mod_ring b) mod (CARD ('q)))" 
    using pow_mod_order_GT CARD_q asmpt by blast
  also have "=  x [^]GTto_int_mod_ring (a + b)"
    by (simp add: plus_mod_ring.rep_eq to_int_mod_ring.rep_eq)
  finally show "x [^]GTto_int_mod_ring a GTx [^]GTto_int_mod_ring b = x [^]GTto_int_mod_ring (a + b)" .
qed

subsubsection ‹bilinearity operations for mod\_ring elements›

lemma e_bilinear[simp]: "P  carrier Gp  Q  carrier Gp  
   e (P [^]Gp(to_int_mod_ring (a::'q mod_ring))) (Q [^]Gp(to_int_mod_ring b)) 
= (e P Q) [^]GT(to_int_mod_ring (a*b))"
proof -
  assume asm: "P  carrier Gp  Q  carrier Gp"
  then have "e (P [^] to_int_mod_ring a) (Q [^] to_int_mod_ring b) = e P Q [^]GT(to_int_mod_ring a * to_int_mod_ring b)"
    by simp
   also have " = (e P Q [^]GT((to_int_mod_ring a * to_int_mod_ring b) mod CARD ('q)))"
     using CARD_q pow_mod_order_GT asm e_symmetric by blast
   also have "= e P Q [^]GTto_int_mod_ring (a * b)"
     by (simp add: times_mod_ring.rep_eq to_int_mod_ring.rep_eq)
   finally  show "e (P [^] to_int_mod_ring a) (Q [^] to_int_mod_ring b) = e P Q [^]GTto_int_mod_ring (a * b)"
     .
qed

lemma e_linear_in_fst: 
  assumes "P  carrier Gp  Q  carrier Gp"
  shows "e (P [^]Gp(to_int_mod_ring (a::'q mod_ring))) (Q) = (e P Q) [^]GT(to_int_mod_ring a)"
proof -
  have "e (P [^]Gpto_int_mod_ring a) Q = e (P [^]Gpto_int_mod_ring a) (Q [^]Gpto_int_mod_ring (1::'q mod_ring))" using assms by simp
  also have "... = (e P Q) [^]GT(to_int_mod_ring (a*(1::'q mod_ring)))" using assms e_bilinear by fast
  also have "=(e P Q) [^]GT(to_int_mod_ring a)" by simp
  finally show "e (P [^]Gp(to_int_mod_ring a)) Q = (e P Q) [^]GT(to_int_mod_ring a)" .
qed

lemma e_linear_in_snd: 
assumes "P  carrier Gp  Q  carrier Gp"
shows "e (P) (Q [^]Gp(to_int_mod_ring (a::'q mod_ring))) = (e P Q) [^]GT(to_int_mod_ring a)"
proof -
have "e P (Q [^]Gpto_int_mod_ring a) = e (P [^]Gpto_int_mod_ring (1::'q mod_ring)) (Q [^]Gpto_int_mod_ring a)" using assms by simp
  also have "... = (e P Q) [^]GT(to_int_mod_ring ((1::'q mod_ring)*a))" using assms e_bilinear by fast
  also have "=(e P Q) [^]GT(to_int_mod_ring a)" by simp
  finally show "e P (Q [^]Gpto_int_mod_ring a) = e P Q [^]GTto_int_mod_ring a" .
qed

lemma addition_in_exponents_on_e[simp]: 
  assumes "x  carrier Gp  y  carrier Gp "
  shows "(e x y) ^GTa GT(e x y) ^GTb = (e x y) ^GT(a+b)"
  using assms
  by (metis PiE e_symmetric mod_ring_pow_mult_GT)

lemma e_from_generators_ne_1: "e gGpgGp 𝟭GT⇙"
proof 
  assume asm: "e gGpgGp= 𝟭GT⇙"
  have "P Q. P  carrier Gp  Q  carrier Gp  e P Q = 𝟭GT⇙" 
  proof(intro allI)
    fix P Q
    show "P  carrier Gp  Q  carrier Gp  e P Q = 𝟭GT⇙ "
    proof 
      assume "P  carrier Gp  Q  carrier Gp"
      then obtain p q::int where "gGp[^]Gpp = P  gGp[^]Gpq = Q"
        by (metis Gp.generatorE int_pow_int)
      then have "e P Q = e (gGp[^]Gpp) (gGp[^]Gpq)"
        by blast
      also have " = e gGpgGp[^]GT(p*q)"
        by force
      also have " =  𝟭GT[^]GT(p*q)"
        using asm by argo
      also have " =  𝟭GT⇙"
        by fastforce
      finally show "e P Q = 𝟭GT⇙" .
    qed
  qed
  then show "False" using e_non_degeneracy by blast
qed

lemma pow_on_eq_card_GT[simp]: "(gGT^GTx = gGT^GTy) = (x=y)"
proof
  assume assm: "gGT^GTx = gGT^GTy"
  then have "gGT[^]GTto_int_mod_ring x = gGT[^]GTto_int_mod_ring y"
    using assm by blast
  then have "gGT[^]GTnat (to_int_mod_ring x) = gGT[^]GTnat (to_int_mod_ring y)" 
    using to_int_mod_ring_ge_0[of "x"] to_int_mod_ring_ge_0[of "y"] by fastforce
  then have "[nat (to_int_mod_ring x) = nat (to_int_mod_ring y)] (mod order GT)"
    using GT.pow_generator_eq_iff_cong GT.finite_carrier by fast
  then have "[to_int_mod_ring x = to_int_mod_ring y] (mod order GT)" 
    using to_int_mod_ring_ge_0[of "x"] to_int_mod_ring_ge_0[of "y"]
    by (metis cong_int_iff int_nat_eq)
  then have "[to_int_mod_ring x = to_int_mod_ring y] (mod p)" 
    using CARD_GT by fast
  then have "to_int_mod_ring x = to_int_mod_ring y"
    by (metis arith_simps(49) to_int_mod_ring_add to_int_mod_ring_hom.hom_0_iff
        unique_euclidean_semiring_class.cong_def CARD_q)
  then show "x = y" by force
next 
  assume "x = y"
  then show "gGT^GTx = gGT^GTy" by fast
qed

lemma pow_on_eq_card_GT_carrier_ext'[simp]: 
  "((e gGpgGp))^GTx = ((e gGpgGp))^GTy  x=y"
proof 
  assume g_pow_x_eq_g_pow_y: "e g g ^GTx = e g g ^GTy"
  obtain g_exp::nat where "e g g = gGT[^]GTg_exp"
    using GT.generatorE e_g_g_in_carrier_GT by blast
  then have g_exp: "e g g = gGT^GT(of_int_mod_ring (int g_exp))"
    by (metis CARD_GT GT.pow_generator_mod_int math_primitives.CARD_q math_primitives_axioms int_pow_int of_int_mod_ring.rep_eq to_int_mod_ring.rep_eq)
  let ?g_exp = "of_int_mod_ring (int g_exp)"
  have "(e g g)^GTx =  gGT^GT(of_int_mod_ring (int g_exp) * x)"
    using g_exp
    by (metis CARD_GT GT.generator_closed GT.int_pow_pow GT.pow_generator_mod_int math_primitives.CARD_q math_primitives_axioms times_mod_ring.rep_eq to_int_mod_ring.rep_eq)
  moreover have "(e g g)^GTy = gGT^GT(of_int_mod_ring (int g_exp) * y)"
    using g_exp
    by (metis CARD_GT GT.generator_closed GT.int_pow_pow GT.pow_generator_mod_int math_primitives.CARD_q math_primitives_axioms times_mod_ring.rep_eq to_int_mod_ring.rep_eq)
  ultimately show "x =y"
    using g_pow_x_eq_g_pow_y pow_on_eq_card_GT e_from_generators_ne_1 g_exp by force
next 
    assume "x = y"
    then show "(e gGpgGp) ^GTx = (e gGpgGp) ^GTy" 
      by blast
  qed

end

end