Skip to content

Commit 7859b9d

Browse files
committed
Adds theories/algebra/ZqCentered.ec providing the centered (signed) integer representation of Z/pZ elements.
1 parent cc2baa4 commit 7859b9d

1 file changed

Lines changed: 300 additions & 0 deletions

File tree

theories/algebra/ZqCentered.ec

Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
(* ==================================================================== *)
2+
require import AllCore IntDiv.
3+
require import StdOrder.
4+
(*---*) import IntOrder.
5+
require ZModP.
6+
7+
(* ==================================================================== *)
8+
(* Centered (signed) representation of elements of the ring Z/pZ. *)
9+
(* *)
10+
(* For p >= 2, the centered representative `crepr : zmod -> int' maps *)
11+
(* every element to the unique integer in the half-open centered *)
12+
(* interval [(p+1)/2 - p, (p+1)/2). For odd primes p > 2 this interval *)
13+
(* is exactly {-(p-1)/2, ..., (p-1)/2}, the standard "balanced" *)
14+
(* representation used in lattice-based cryptography. *)
15+
(* *)
16+
(* Provides: *)
17+
(* - `to_crepr', `crepr' (centered representative on int and Zq) *)
18+
(* - range, round-trip, equality lemmas *)
19+
(* - algebraic laws under +, * *)
20+
(* - centered absolute value `"`|_|"' with triangle / product / *)
21+
(* monotonicity inequalities *)
22+
(* *)
23+
(* The sub-theory `ZqCenteredField' adds prime-only lemmas: *)
24+
(* - `creprN', `creprN2', `creprND' (negation symmetry) *)
25+
(* - `abs_zpN' *)
26+
(* ==================================================================== *)
27+
28+
(* ==================================================================== *)
29+
abstract theory ZqCentered.
30+
31+
clone include ZModP.ZModRing.
32+
33+
(* -------------------------------------------------------------------- *)
34+
(* Auxiliary congruence lemmas. *)
35+
36+
lemma zmodcgr_ceq a b :
37+
(p + 1) %/ 2 - p <= a < (p + 1) %/ 2
38+
=> (p + 1) %/ 2 - p <= b < (p + 1) %/ 2
39+
=> zmodcgr a b
40+
=> a = b
41+
by case (0 <= a); case (0 <= b); smt().
42+
43+
lemma zmodcgr_transitive b a c :
44+
zmodcgr a b => zmodcgr b c => zmodcgr a c.
45+
proof. smt(). qed.
46+
47+
lemma zmodcgr_mp a : zmodcgr a (a - p) by smt().
48+
49+
lemma zmodcgr_refl a b : zmodcgr a b <=> zmodcgr b a by smt().
50+
51+
(* -------------------------------------------------------------------- *)
52+
(* Centered representative on int. *)
53+
(* *)
54+
(* "Halfway" is rounded down: when 2 %| p the unique value with *)
55+
(* asint = p/2 maps to -p/2. For odd p the choice is irrelevant. *)
56+
57+
op to_crepr (x : int) : int =
58+
let y = x %% p in
59+
if (p + 1) %/ 2 <= y then y - p else y.
60+
61+
lemma to_crepr_idempotent : to_crepr \o to_crepr = to_crepr.
62+
proof. by rewrite fun_ext /(\o) => x; smt(ge2_p). qed.
63+
64+
lemma rg_to_crepr x :
65+
(p + 1) %/ 2 - p <= to_crepr x < (p + 1) %/ 2.
66+
proof. smt(ge2_p rg_asint). qed.
67+
68+
lemma to_crepr_zmodcgr x : zmodcgr x (to_crepr x).
69+
proof. smt(ge2_p). qed.
70+
71+
lemma to_crepr_id x :
72+
(p + 1) %/ 2 - p <= x < (p + 1) %/ 2 => to_crepr x = x.
73+
proof. smt(). qed.
74+
75+
lemma to_crepr_eq x y : to_crepr x = to_crepr y <=> zmodcgr x y.
76+
proof. rewrite /to_crepr /= /#. qed.
77+
78+
(* -------------------------------------------------------------------- *)
79+
(* Centered representative on Zq. *)
80+
81+
op crepr (x : zmod) : int =
82+
let y = asint x in
83+
if (p + 1) %/ 2 <= y then y - p else y.
84+
85+
lemma rg_crepr x :
86+
(p + 1) %/ 2 - p <= crepr x < (p + 1) %/ 2.
87+
proof. smt(ge2_p rg_asint). qed.
88+
89+
lemma crepr_eq x y : crepr x = crepr y <=> x = y.
90+
proof. smt(rg_asint asint_eq). qed.
91+
92+
lemma asint_crepr x : asint x = (crepr x) %% p.
93+
proof.
94+
rewrite /crepr /=.
95+
case ((p + 1) %/ 2 <= asint x) => _.
96+
- by rewrite -modzDr; smt(modz_small rg_asint).
97+
- by smt(modz_small rg_asint).
98+
qed.
99+
100+
lemma creprK (x : zmod) : inzmod (crepr x) = x.
101+
proof.
102+
rewrite /crepr /=.
103+
case ((p + 1) %/ 2 <= asint x) => ?; last by exact asintK.
104+
rewrite inzmod_mod.
105+
suff : (asint x - p) %% p = asint x by smt(asintK).
106+
smt(rg_asint).
107+
qed.
108+
109+
lemma inzmodK_centered x :
110+
(p + 1) %/ 2 - p <= x
111+
=> x < (p + 1) %/ 2
112+
=> crepr (inzmod x) = x.
113+
proof. by rewrite /crepr inzmodK /#. qed.
114+
115+
(* -------------------------------------------------------------------- *)
116+
(* Algebraic laws under multiplication and addition. *)
117+
118+
lemma crepr_mulE x y :
119+
crepr (x * y) = to_crepr (crepr x * crepr y).
120+
proof.
121+
suff : zmodcgr (crepr (x * y)) (crepr x * crepr y).
122+
+ move => *.
123+
have ? := to_crepr_zmodcgr (crepr x * crepr y).
124+
by have : zmodcgr (crepr (x * y)) (to_crepr (crepr x * crepr y));
125+
smt(to_crepr_zmodcgr rg_to_crepr rg_crepr zmodcgr_ceq).
126+
rewrite /crepr /=.
127+
case ((p + 1) %/ 2 <= asint (x * y)) => ?.
128+
- case ((p + 1) %/ 2 <= asint x) => ?.
129+
+ case ((p + 1) %/ 2 <= asint y) => ?.
130+
+ rewrite -modzMm -(zmodcgr_mp (asint x)) -(zmodcgr_mp (asint y)).
131+
by rewrite -(zmodcgr_mp (asint (x * y))) mulE -modzMm modz_mod.
132+
+ rewrite -modzMm -(zmodcgr_mp (asint x)) -(zmodcgr_mp (asint (x * y))).
133+
by rewrite mulE -modzMm modz_mod.
134+
+ case ((p + 1) %/ 2 <= asint y) => ?.
135+
+ rewrite -modzMm -(zmodcgr_mp (asint y)).
136+
by rewrite -(zmodcgr_mp (asint (x * y))) mulE -modzMm modz_mod.
137+
+ rewrite -modzMm -(zmodcgr_mp (asint (x * y))).
138+
by rewrite mulE -modzMm modz_mod.
139+
- case ((p + 1) %/ 2 <= asint x) => ?.
140+
+ case ((p + 1) %/ 2 <= asint y) => ?.
141+
+ rewrite -modzMm -(zmodcgr_mp (asint x)) -(zmodcgr_mp (asint y)).
142+
by rewrite mulE -modzMm modz_mod.
143+
+ rewrite -modzMm -(zmodcgr_mp (asint x)).
144+
by rewrite mulE -modzMm modz_mod.
145+
+ case ((p + 1) %/ 2 <= asint y) => ?.
146+
+ rewrite -modzMm -(zmodcgr_mp (asint y)).
147+
by rewrite mulE -modzMm modz_mod.
148+
+ rewrite -modzMm.
149+
by rewrite mulE -modzMm modz_mod.
150+
qed.
151+
152+
lemma creprD (x y : zmod) :
153+
crepr (x + y) = to_crepr (crepr x + crepr y).
154+
proof.
155+
suff : zmodcgr (crepr (x + y)) (crepr x + crepr y).
156+
+ move => *.
157+
have ? := to_crepr_zmodcgr (crepr x + crepr y).
158+
by have : zmodcgr (crepr (x + y)) (to_crepr (crepr x + crepr y));
159+
smt(to_crepr_zmodcgr rg_to_crepr rg_crepr zmodcgr_ceq).
160+
rewrite /crepr addE /=.
161+
apply (zmodcgr_transitive (asint x + asint y)).
162+
- case ((p + 1) %/ 2 <= (asint x + asint y) %% p) => _.
163+
+ have -> : (asint x + asint y) %% p - p
164+
= (asint x + asint y) %% p + (-1) * p by ring.
165+
by rewrite modzMDr modz_mod.
166+
+ by rewrite modz_mod.
167+
case ((p + 1) %/ 2 <= asint x) => _.
168+
- case ((p + 1) %/ 2 <= asint y) => _.
169+
+ have -> : asint x - p + (asint y - p)
170+
= asint x + asint y + (-2) * p by ring.
171+
by rewrite modzMDr.
172+
+ have -> : asint x - p + asint y
173+
= asint x + asint y + (-1) * p by ring.
174+
by rewrite modzMDr.
175+
- case ((p + 1) %/ 2 <= asint y) => _ //.
176+
have -> : asint x + (asint y - p)
177+
= asint x + asint y + (-1) * p by ring.
178+
by rewrite modzMDr.
179+
qed.
180+
181+
(* -------------------------------------------------------------------- *)
182+
(* Centered absolute value. *)
183+
184+
op "`|_|" (x : zmod) : int = `| crepr x |.
185+
186+
lemma to_crepr_abs x : `|to_crepr x| <= `|x|.
187+
proof. smt(rg_to_crepr). qed.
188+
189+
lemma abs_zp_small (x : int) :
190+
`|x| < p %/ 2 => `|inzmod x| = `|x|.
191+
proof. by move=> ?; rewrite /"`|_|"; smt(ltr_norml inzmodK). qed.
192+
193+
lemma abs_zp_triangle (x y : zmod) :
194+
`|x + y| <= `|x| + `|y|.
195+
proof.
196+
rewrite /"`|_|" creprD.
197+
have := to_crepr_abs (crepr x + crepr y).
198+
smt().
199+
qed.
200+
201+
lemma abs_zp_zero : `|zero| = 0.
202+
proof. by rewrite /"`|_|" /crepr zeroE /=; smt(ge2_p). qed.
203+
204+
lemma abs_zp_one : `|one| = 1.
205+
proof. by rewrite /"`|_|" /crepr /=; rewrite oneE; smt(ge2_p). qed.
206+
207+
lemma ge0_abs_zp (x : zmod) : 0 <= `|x|.
208+
proof. smt(). qed.
209+
210+
lemma abs_zp_ub (x : zmod) : `|x| <= p %/ 2.
211+
proof. smt(rg_asint). qed.
212+
213+
lemma abs_zp_prod (x y : zmod) :
214+
`|x * y| <= `|x| * `|y|.
215+
proof. by rewrite /"`|_|" crepr_mulE; smt(to_crepr_abs). qed.
216+
217+
lemma abs_zpN (x : zmod) : `|x| = `|-x|.
218+
proof.
219+
rewrite /"`|_|" /crepr /=.
220+
case (x = zero) => ?; first by smt(ZModpRing.oppr0).
221+
have ? : asint x <> 0 by have := asint_inj x zero; smt(zeroE).
222+
suff : asint (-x) = p - asint x by smt().
223+
rewrite oppE -modzDl.
224+
suff : (p - asint x) %% p = ((p - asint x) + p) %% p by smt(rg_asint).
225+
by smt(modzDr).
226+
qed.
227+
228+
end ZqCentered.
229+
230+
(* ==================================================================== *)
231+
(* Field version: when p is prime, additionally provide negation *)
232+
(* symmetry for the centered representative. *)
233+
(* ==================================================================== *)
234+
abstract theory ZqCenteredField.
235+
236+
const p : { int | prime p } as prime_p.
237+
238+
clone include ZqCentered with
239+
op p <- p
240+
proof ge2_p by smt(gt1_prime prime_p).
241+
242+
(* prime_p is now in scope; ZqCentered's content is available. *)
243+
244+
lemma modz_small2 a :
245+
p <= a < 2 * p => a %% p = a - p
246+
by smt().
247+
248+
lemma zmodcgrN a :
249+
a <> zero =>
250+
(- asint a) %% p = - asint a %% p + p.
251+
proof.
252+
move => ?; have ? := rg_asint a.
253+
have ? : asint a <> 0 by have := asint_inj a zero; smt(zeroE).
254+
rewrite modNz; 1,2: by smt(prime_p).
255+
rewrite -modzDm modNz //=; 1: smt(prime_p).
256+
suff : (asint a %% p + (p - 1)) %% p = (asint a %% p + (p - 1)) - p by smt().
257+
rewrite (modz_small (asint a) p) 1:/# /=.
258+
by rewrite modz_small2 /#.
259+
qed.
260+
261+
lemma creprN (a : zmod) :
262+
p <> 2 => crepr (-a) = -crepr a.
263+
proof.
264+
have ? := rg_asint a.
265+
rewrite /crepr !oppE; case (a = zero).
266+
+ by move => -> /=; rewrite zeroE /=; smt(prime_p).
267+
move => ? /=; rewrite !zmodcgrN //.
268+
have -> : (- asint a %% p) + p = p - asint a
269+
by smt(rg_asint modz_small edivzP).
270+
have ? : asint a <> 0 by have := asint_inj a zero; smt(zeroE).
271+
case ((p + 1) %/ 2 < asint a); 1: by smt().
272+
case (asint a < (p + 1) %/ 2); 1: by smt().
273+
move => *; have -> : asint a = (p + 1) %/ 2 by smt(rg_asint).
274+
have ? : p + 1 = (p + 1) %/ 2 + (p + 1) %/ 2; last by smt().
275+
have ? : p %% 2 <> 0.
276+
+ have := prime_p.
277+
rewrite /prime => [#? Hmod].
278+
by have := Hmod 2 => /= /#.
279+
smt().
280+
qed.
281+
282+
lemma creprN2 (a : zmod) :
283+
p = 2 => crepr (-a) = crepr a.
284+
proof.
285+
move => Hp.
286+
have ? := rg_asint a.
287+
rewrite /crepr !oppE; case (a = zero).
288+
+ by move => -> /=; rewrite zeroE /=; smt(prime_p).
289+
move => ? /=; rewrite !zmodcgrN /#.
290+
qed.
291+
292+
lemma creprND (a b : zmod) :
293+
crepr (a - b) = to_crepr (crepr a - crepr b).
294+
proof.
295+
have ? := rg_asint a; have ? := rg_asint b.
296+
case (p = 2); 2: by smt(creprD creprN).
297+
by smt(creprD creprN2).
298+
qed.
299+
300+
end ZqCenteredField.

0 commit comments

Comments
 (0)