-
Notifications
You must be signed in to change notification settings - Fork 9
/
PRF.v
423 lines (375 loc) · 12.3 KB
/
PRF.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
(** PRF Example
Inspired by "State Separation for Code-Based Game-Playing Proofs"
by Brzuska et al.
Appendix A.
"Given a pseudorandom function (PRF) we construct a symmetric encryption
scheme that is indistinguishable under chosen plaintext attacks (IND-CPA)."
*)
From SSProve.Relational Require Import OrderEnrichedCategory GenericRulesSimple.
Set Warnings "-notation-overridden,-ambiguous-paths".
From mathcomp Require Import all_ssreflect all_algebra reals distr realsum
ssrnat ssreflect ssrfun ssrbool ssrnum eqtype choice seq.
Set Warnings "notation-overridden,ambiguous-paths".
From SSProve.Mon Require Import SPropBase.
From SSProve.Crypt Require Import Axioms ChoiceAsOrd SubDistr Couplings
UniformDistrLemmas FreeProbProg Theta_dens RulesStateProb
pkg_core_definition choice_type pkg_composition pkg_rhl Package Prelude.
From Coq Require Import Utf8.
From extructures Require Import ord fset fmap.
Import SPropNotations.
Import PackageNotation.
From Equations Require Import Equations.
Require Equations.Prop.DepElim.
Set Equations With UIP.
Set Bullet Behavior "Strict Subproofs".
Set Default Goal Selector "!".
Set Primitive Projections.
Import Num.Def.
Import Num.Theory.
Import Order.POrderTheory.
Section PRF_example.
Context (n : nat).
Definition Words_N : nat := 2^n.
Definition Words_N_pos : Positive Words_N := _.
Definition Words : choice_type := chFin (mkpos Words_N).
Definition Key_N : nat := 2^n.
Definition Key_N_pos : Positive Key_N := _.
Definition Key : choice_type := chFin (mkpos Key_N).
(* TW: Is this normal that this definition is so big? *)
#[program] Definition plus : Words → Key → Words :=
λ w k,
@Ordinal _ (BinNat.N.to_nat (BinNat.N.lxor (BinNat.N.of_nat (nat_of_ord w)) (BinNat.N.of_nat (nat_of_ord k)))) _.
Next Obligation.
destruct w as [w Hw], k as [k Hk].
destruct w as [|Pw], k as [|Pk].
1:{ simpl. assumption. }
1:{
simpl.
rewrite Pnat.SuccNat2Pos.id_succ.
assumption.
}
1:{
simpl.
rewrite Pnat.SuccNat2Pos.id_succ.
assumption.
}
remember (succn Pw) as w.
remember (succn Pk) as k.
assert (
∀ m,
(2 ^ m)%nat = BinNat.N.to_nat (BinNat.N.pow (BinNums.Npos (BinNums.xO 1%AC)) (BinNat.N.of_nat m))
) as H.
{ induction m.
- reflexivity.
- rewrite expnSr.
rewrite Nnat.Nat2N.inj_succ.
rewrite BinNat.N.pow_succ_r'.
rewrite Nnat.N2Nat.inj_mul.
rewrite PeanoNat.Nat.mul_comm.
apply f_equal2.
+ apply IHm.
+ reflexivity.
}
unfold Words_N, Key_N in *.
move: (BinNat.N.log2_lxor (BinNat.N.of_nat w) (BinNat.N.of_nat k)) => Hbound.
assert (
BinNat.N.lt (BinNat.N.log2 (BinNat.N.of_nat w)) (BinNat.N.of_nat n)
) as H1.
{ rewrite -BinNat.N.log2_lt_pow2.
2:{
rewrite Heqw. rewrite Nnat.Nat2N.inj_succ.
apply BinNat.N.lt_0_succ.
}
unfold BinNat.N.lt.
rewrite Nnat.N2Nat.inj_compare.
rewrite PeanoNat.Nat.compare_lt_iff.
rewrite Nnat.Nat2N.id.
rewrite -H.
apply /ltP.
apply Hw.
}
assert (
BinNat.N.lt (BinNat.N.log2 (BinNat.N.of_nat k)) (BinNat.N.of_nat n)
) as H2.
{ rewrite -BinNat.N.log2_lt_pow2.
2:{
rewrite Heqk. rewrite Nnat.Nat2N.inj_succ.
apply BinNat.N.lt_0_succ.
}
unfold BinNat.N.lt.
rewrite Nnat.N2Nat.inj_compare.
rewrite PeanoNat.Nat.compare_lt_iff.
rewrite Nnat.Nat2N.id.
rewrite -H.
apply /ltP.
apply Hk.
}
move: (BinNat.N.max_lub_lt _ _ _ H1 H2) => Hm.
destruct ((BinNat.N.lxor (BinNat.N.of_nat w) (BinNat.N.of_nat k)) == BinNat.N0) eqn:H0.
1:{
simpl. move: H0. move /eqP => H0. rewrite H0. simpl.
rewrite expn_gt0. apply /orP. left. auto.
}
move: (BinNat.N.le_lt_trans _ _ _ Hbound Hm).
rewrite -BinNat.N.log2_lt_pow2.
2:{
apply BinNat.N.neq_0_lt_0.
move: H0. move /eqP. auto.
}
unfold BinNat.N.lt.
rewrite Nnat.N2Nat.inj_compare.
rewrite PeanoNat.Nat.compare_lt_iff.
move => Hlt.
apply /ltP.
simpl in *.
rewrite H.
assumption.
Qed.
Notation "m ⊕ k" := (plus m k) (at level 70).
Lemma plus_involutive :
∀ m k, (m ⊕ k) ⊕ k = m.
Proof.
intros m k.
move: ord_inj => Hordinj.
unfold injective in Hordinj.
apply Hordinj.
destruct m. cbn.
rewrite Nnat.N2Nat.id.
rewrite BinNat.N.lxor_assoc.
rewrite BinNat.N.lxor_nilpotent.
rewrite BinNat.N.lxor_0_r.
rewrite Nnat.Nat2N.id.
reflexivity.
Qed.
#[local] Open Scope package_scope.
Definition key_location : Location := ('option Key ; 0).
Definition plain_location : Location := (Words ; 1).
Definition cipher_location : Location := (Words ; 2).
Definition i0 : nat := 3.
Definition i1 : nat := 4.
Definition i2 : nat := 5.
Definition salt_location : Location := ('nat ; 6).
Definition table_location : Location :=
(chMap 'nat ('fin (2^n)%N) ; 7).
Definition rel_loc : {fset Location} :=
fset [:: key_location ; table_location ].
Context (PRF : Words → Key → Key).
Notation " 'word " := ('fin (2^n)%N) (in custom pack_type at level 2).
Notation " 'key " := ('fin (2^n)%N) (in custom pack_type at level 2).
Definition i_key : nat := 2^n.
Definition i_words : nat := 2^n.
Definition enc {L : { fset Location }} (m : Words) (k : Key) :
code L [interface] ('fin (2^n) × 'fin (2^n)) :=
{code
r ← sample uniform i_words ;;
let pad := PRF r k in
let c := m ⊕ pad in
ret (r, c)
}.
Definition kgen : code fset0 [interface] 'fin (2^n) :=
{code
k ← sample uniform i_key ;;
ret k
}.
Definition dec (c : Words) (k : Key) :
code
(fset [:: key_location; table_location])
[interface]
('fin (2^n) × 'fin (2^n)) :=
enc k c.
Definition EVAL_location_tt := (fset [:: key_location]).
Definition EVAL_location_ff := (fset [:: table_location]).
Definition EVAL_pkg_tt :
package EVAL_location_tt [interface]
[interface #val #[i0] : 'word → 'key ] :=
[package
#def #[i0] (r : 'word) : 'key
{
k_init ← get key_location ;;
match k_init with
| None =>
k ← sample uniform i_key ;;
#put key_location := Some k ;;
ret (PRF r k)
| Some k_val =>
ret (PRF r k_val)
end
}
].
Definition EVAL_pkg_ff :
package EVAL_location_ff [interface]
[interface #val #[i0] : 'word → 'key ] :=
[package
#def #[i0] (r : 'word) : 'key
{
T ← get table_location ;;
match getm T r with
| None =>
T_key ← sample uniform i_key ;;
#put table_location := (setm T r T_key) ;;
ret T_key
| Some T_key => ret T_key
end
}
].
(* TODO Not the most satisfying, it would be nice to think of something else
This might come with more automation to deal with the GamePair type.
*)
Definition EVAL : loc_GamePair [interface #val #[i0] : 'word → 'key ] :=
λ b, if b then {locpackage EVAL_pkg_tt } else {locpackage EVAL_pkg_ff }.
Definition MOD_CPA_location : {fset Location} := fset0.
Definition MOD_CPA_tt_pkg :
package MOD_CPA_location [interface #val #[i0] : 'word → 'key ]
[interface #val #[i1] : 'word → 'word × 'word ] :=
[package
#def #[i1] (m : 'word) : 'word × 'word
{
#import {sig #[i0] : 'word → 'key } as eval ;;
r ← sample uniform i_words ;;
pad ← eval r ;;
let c := m ⊕ pad in
ret (r, c)
}
].
Definition MOD_CPA_ff_pkg :
package MOD_CPA_location [interface #val #[i0] : 'word → 'key]
[interface #val #[i1] : 'word → 'word × 'word ]:=
[package
#def #[i1] (m : 'word) : 'word × 'word
{
#import {sig #[i0] : 'word → 'key } as eval ;;
r ← sample uniform i_words ;;
m' ← sample uniform i_words ;;
pad ← eval r ;;
let c := (m' ⊕ pad) in
ret (r, c)
}
].
Definition IND_CPA_location : {fset Location} := fset [:: key_location].
Definition IND_CPA_pkg_tt :
package IND_CPA_location
[interface]
[interface #val #[i1] : 'word → 'word × 'word ] :=
[package
#def #[i1] (m : 'word) : 'word × 'word
{
k ← get key_location ;;
match k with
| None =>
k_val ← sample uniform i_key ;;
#put key_location := Some k_val ;;
enc m k_val
| Some k_val =>
enc m k_val
end
}
].
Definition IND_CPA_pkg_ff :
package IND_CPA_location
[interface]
[interface #val #[i1] : 'word → 'word × 'word ] :=
[package
#def #[i1] (m : 'word) : 'word × 'word
{
k ← get key_location ;;
match k with
| None =>
k_val ← sample uniform i_key ;;
#put key_location := Some k_val ;;
m' ← sample uniform i_words ;;
enc m' k_val
| Some k_val =>
m' ← sample uniform i_words ;;
enc m' k_val
end
}
].
Definition IND_CPA :
loc_GamePair [interface #val #[i1] : 'word → 'word × 'word ] :=
λ b,
if b then {locpackage IND_CPA_pkg_tt } else {locpackage IND_CPA_pkg_ff }.
Local Open Scope ring_scope.
Definition prf_epsilon A := Advantage EVAL A.
Definition statistical_gap :=
AdvantageE (MOD_CPA_ff_pkg ∘ EVAL false) (MOD_CPA_tt_pkg ∘ EVAL false).
Lemma IND_CPA_equiv_false :
IND_CPA false ≈₀ MOD_CPA_ff_pkg ∘ (EVAL true).
Proof.
(* We go to the relation logic using equality as invariant. *)
eapply eq_rel_perf_ind_eq.
simplify_eq_rel m.
simplify_linking.
(* We now conduct the proof in relational logic. *)
ssprove_swap_rhs 1%N.
ssprove_swap_rhs 0%N.
ssprove_sync_eq. cbn. intros [k|].
- cbn. ssprove_swap_rhs 0%N.
eapply rpost_weaken_rule.
1: eapply rreflexivity_rule.
cbn. intros [? ?] [? ?] e. inversion e. intuition auto.
- cbn.
ssprove_swap_rhs 0%N.
ssprove_swap_rhs 1%N.
ssprove_swap_rhs 0%N.
ssprove_swap_rhs 2%N.
ssprove_swap_rhs 1%N.
eapply rpost_weaken_rule. 1: eapply rreflexivity_rule.
cbn. intros [? ?] [? ?] e. inversion e. intuition auto.
Qed.
Lemma IND_CPA_equiv_true :
MOD_CPA_tt_pkg ∘ (EVAL true) ≈₀ IND_CPA true.
Proof.
(* We go to the relation logic using equality as invariant. *)
eapply eq_rel_perf_ind_eq.
simplify_eq_rel m.
simplify_linking.
(* We now conduct the proof in relational logic. *)
ssprove_swap_lhs 0%N.
ssprove_sync_eq. cbn. intros [k|].
- cbn. eapply rpost_weaken_rule. 1: eapply rreflexivity_rule.
cbn. intros [? ?] [? ?] e. inversion e. intuition auto.
- cbn.
ssprove_swap_rhs 1%N.
ssprove_swap_rhs 0%N.
eapply rpost_weaken_rule. 1: eapply rreflexivity_rule.
cbn. intros [? ?] [? ?] e. inversion e. intuition auto.
Qed.
(** Security of PRF
The bound is given by using the triangle inequality several times,
using the following chain:
IND_CPA false ≈ MOD_CPA_ff_pkg ∘ EVAL true
≈ MOD_CPA_ff_pkg ∘ EVAL false
≈ MOD_CPA_tt_pkg ∘ EVAL false
≈ MOD_CPA_tt_pkg ∘ EVAL true
≈ IND_CPA true
*)
Theorem security_based_on_prf :
∀ LA A,
ValidPackage LA
[interface #val #[i1] : 'word → 'word × 'word ] A_export A →
fdisjoint LA (IND_CPA false).(locs) →
fdisjoint LA (IND_CPA true).(locs) →
Advantage IND_CPA A <=
prf_epsilon (A ∘ MOD_CPA_ff_pkg) +
statistical_gap A +
prf_epsilon (A ∘ MOD_CPA_tt_pkg).
Proof.
intros LA A vA hd₀ hd₁. unfold prf_epsilon, statistical_gap.
rewrite !Advantage_E.
ssprove triangle (IND_CPA false) [::
MOD_CPA_ff_pkg ∘ EVAL true ;
MOD_CPA_ff_pkg ∘ EVAL false ;
MOD_CPA_tt_pkg ∘ EVAL false ;
MOD_CPA_tt_pkg ∘ EVAL true
] (IND_CPA true) A
as ineq.
eapply le_trans. 1: exact ineq.
clear ineq.
erewrite IND_CPA_equiv_false. all: eauto.
2:{ simpl. unfold MOD_CPA_location. rewrite fset0U. auto. }
erewrite IND_CPA_equiv_true. all: eauto.
2:{ simpl. unfold MOD_CPA_location. rewrite fset0U. auto. }
rewrite GRing.add0r GRing.addr0.
rewrite !Advantage_link. rewrite Advantage_sym. auto.
Qed.
End PRF_example.