|
| 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