Library BBS_Asm_CryptoProof
This file contains the proof of unpredictability of the implementation in Assembly of
the Blum-Blum-Shub (BBS) pseudorandom bit generator. Security is based on the intractability
of the quadratic residuosity problem.
Require Import Euclid List Znumtheory Zpow_facts Rbase.
From mathcomp Require Import ssreflect ssrbool.
Require Import ZArith_ext.
Require Import listbit.
Add LoadPath "./toolbox".
Require MiscLists BBS.
Add LoadPath "../cryptoasm".
Require bbs_encode_decode.
Local Close Scope Z_scope.
Lemma euclid_unique : forall m n q r q' r',
0 < n -> m = q * n + r -> m = q' * n + r' -> n > r -> n > r' -> q = q' /\ r = r'.
Proof.
intros m n q r q' r' Hn Hq Hq' Hr Hr'.
suff H : Z_of_nat q = Z_of_nat q' /\ Z_of_nat r = Z_of_nat r' by omega.
apply Zdiv_mod_unique with (Z_of_nat n).
- rewrite Zabs_eq; omega.
- rewrite Zabs_eq; omega.
- rewrite mult_comm in Hq.
rewrite mult_comm in Hq'.
rewrite -2!inj_mult -2!inj_plus; congruence.
Qed.
Definition ceiling_div (m n : nat) (H : 0 < n) :=
if eq_nat_dec (proj1_sig (modulo n H m)) O then
proj1_sig (quotient n H m)
else
S (proj1_sig (quotient n H m)).
Lemma lt_0_ceiling_div : forall m n, 0 < m ->
forall H : 0 < n, 0 < ceiling_div m n H.
Proof.
rewrite /ceiling_div => m n Hm Hn.
destruct (modulo n Hn m) as [r [q [H1 H2]]] => /=.
destruct (quotient n Hn m) as [q' [r' [H3 H4]]] => /=.
destruct (eq_nat_dec r 0) as [H5 | H5] => /=.
- apply neq_O_lt => Hq.
subst.
rewrite /= in Hm; rewrite /= plus_0_r in H1.
destruct q.
+ omega.
+ induction q as [| q IH].
* omega.
* apply IH.
rewrite /= in H1 *.
by intuition.
- omega.
Qed.
Lemma le_mult_ceiling_div : forall m n (H:0<n), m <= n * ceiling_div m n H.
Proof.
rewrite /ceiling_div => m n Hn.
destruct (modulo n Hn m) as [r [q [H1 H2]]] => /=.
destruct (quotient n Hn m) as [q' [r' [H3 H4]]] => /=.
have {H3 H4}[H5 H6] : q = q' /\ r = r' by apply euclid_unique with m n.
subst q' r'.
destruct (eq_nat_dec r 0) as [H3 | H3] => /=.
- subst r m.
by rewrite plus_0_r mult_comm.
- subst m.
rewrite (mult_comm n) /=; omega.
Qed.
Local Open Scope Z_scope.
Lemma Zmult_le_lt : forall m n p, 1 < m -> 0 < n -> m * n <= p -> n < p.
Proof.
intros m n p Hm Hn H.
apply Zmult_lt_reg_r with m.
- omega.
- rewrite Zmult_comm in H.
apply Zle_lt_trans with p => //.
rewrite -{1}(Zmult_1_r p).
apply Zmult_lt_compat_l => //.
have H0 : (0 < n * m) by apply Zmult_lt_0_compat => //; omega.
omega.
Qed.
Lemma lt_0_N_digits : forall n, 1 < n -> 0 < N_digits n.
Proof. elim => //; case=> [p|p|] Hp //=; by apply Zle_lt_succ, log_inf_correct1. Qed.
Local Open Scope zarith_ext_scope.
We show that the restrictions are decidable.
Lemma Restrictions_dec : forall nn nk modu seed,
{bbs_encode_decode.Implem.Restrictions nn nk modu seed} +
{~ bbs_encode_decode.Implem.Restrictions nn nk modu seed}.
Proof.
intros nn nk modu seed.
unfold bbs_encode_decode.Implem.Restrictions.
destruct (le_lt_dec nk 0) as [H1 | H1]; auto with zarith.
- destruct (Z_lt_dec 0 modu) as [H2 | H2]; auto with zarith.
destruct (Z_lt_dec modu (ZArith_ext.Zpower 2 (nk * 32))) as [H3 | H3]; auto with zarith.
destruct (Zodd_dec modu) as [H4 | H4]; try tauto.
destruct (Z_le_dec 0 seed) as [H5 | H5]; auto with zarith.
destruct (Z_lt_dec seed modu) as [H6 | H6]; auto with zarith.
destruct (Z_lt_dec (4 * Z_of_nat (4 * nk + nn + 2)) (2^^32)) as [H7 | H7]; auto with zarith.
tauto.
- destruct (Z_lt_dec 0 modu) as [H2 | H2]; auto with zarith.
destruct (Z_lt_dec modu (ZArith_ext.Zpower 2 (nk * 32))) as [H3 | H3]; auto with zarith.
destruct (Zodd_dec modu) as [H4 | H4]; try tauto.
destruct (Z_le_dec 0 seed) as [H5 | H5]; auto with zarith.
destruct (Z_lt_dec seed modu) as [H6 | H6]; auto with zarith.
destruct (Z_lt_dec (4 * Z_of_nat (4 * nk + nn + 2)) (2^^32)) as [H7 | H7]; auto with zarith.
tauto.
Qed.
Section BBS.
Variables p q : Z.
Lemma gt_32_0 : (32 > 0)%nat. Proof. omega. Qed.
Lemma tech1 : p * q < 2 ^^ (32 * (ceiling_div (S (Zabs_nat (N_digits (p * q)))) 32 gt_32_0)).
Proof.
unfold ceiling_div.
destruct (modulo 32 gt_32_0 (S (Zabs_nat (N_digits (p * q))))) as [r1 [q1 [H1 H2]]].
destruct (quotient 32 gt_32_0 (S (Zabs_nat (N_digits (p * q))))) as [q2 [r2 [H3 H4]]].
simpl proj1_sig.
have [H5 H6] : q1 = q2 /\ r1 = r2.
apply euclid_unique with (S (Zabs_nat (N_digits (p * q)))) (32%nat) => //.
by repeat constructor.
subst q2 r2.
clear H3 H4.
destruct (eq_nat_dec r1 0) as [H | H]; rewrite [mult]lock /= -lock.
- subst r1.
rewrite plus_0_r mult_comm in H1.
rewrite -H1.
destruct (p * q) => //.
+ destruct (log_inf_correct p0) as [H3 [H4 H5] ].
eapply Zlt_le_trans; first by apply H5.
rewrite two_p_S //.
(match goal with |- context [2 ^^ (S ?x)] => replace (S x) with (1 + x)%nat end) ; trivial.
rewrite Zpower_is_exp.
simpl Zpower.
apply Zmult_le_compat_l; last by done.
rewrite /two_p.
destruct (log_inf p0) => //.
- rewrite two_power_pos_correct Zpower_pos_nat Zpower_nat_Zpower
(Zpos_eq_Z_of_nat_o_nat_of_P p1) Zabs_nat_Z_of_nat.
by apply Zle_refl.
- contradict H3; by auto.
+ apply Zle_lt_trans with 0 => //.
by apply Zpower_0.
- rewrite /N_digits in H1.
destruct (p * q).
+ by apply Zpower_0.
+ destruct (log_inf_correct2 p0) as [_ Hp0].
eapply Zlt_trans; first by apply Hp0.
apply Zle_lt_trans with (Zpower_nat 2 (1 + (Zabs_nat (log_inf p0)))).
- rewrite two_p_S.
+ rewrite Zpower_nat_is_exp (_ : Zpower_nat 2 1 = 2) //.
apply Zmult_le_compat_l; last by omega.
destruct (log_inf p0) => //.
+ rewrite /= two_power_pos_nat two_power_nat_correct; omega.
+ rewrite /= Zpower_nat_Zpower.
move: (Zpower_0 (nat_of_P p1)) => X; omega.
+ by apply log_inf_correct1.
- rewrite Zpower_nat_Zpower [plus _ _]/= H1.
apply expZ_2_lt; omega.
+ apply Zlt_trans with 0 => //.
by apply Zpower_0.
Qed.
Hypothesis p_prime : prime p.
Hypothesis q_prime : prime q.
Lemma firstn_bbs : forall len1 len2 seed, (len1 <= len2)%nat ->
firstn len1 (BBS.bbs p q p_prime q_prime len2 seed) = BBS.bbs p q p_prime q_prime len1 seed.
Proof.
rewrite /BBS.bbs /mult.
induction len1 as [|len1 IH] => //.
destruct len2 as [|len2].
+ intros seed H.
contradict H; omega.
+ intros seed H.
rewrite MiscLists.firstn_cons IH //; omega.
Qed.
Implem.bbs_fun and BBS.bbs return equal results when the seed seed is restricted to
the multiplicative group pf integers modulo p*q.
Lemma bbs_fun_bbs : forall len seed,
bbs_fun len (proj1_sig seed) (p * q) = BBS.bbs p q p_prime q_prime len seed.
Proof.
rewrite /bbs_fun /BBS.bbs.
move=> len [seed Hseed] /=.
move: seed Hseed.
induction len as [ | len IH] => // seed Hseed /=; f_equal.
+ rewrite /Zstar.parity /=.
case: (Zodd_dec ((seed * seed) mod (p * q))) => H.
* by apply/Zodd_Zodd_bool.
* move/Zodd_Zodd_bool : H.
move/negP.
by destruct Zodd_bool.
+ rewrite Zmult_1_r.
erewrite IH; reflexivity.
Qed.
The semantics of bbs_asm:
Require Import Group.
Definition bbs_asm_sem (len : nat)
(seed : Zstar.Zstar _ (Zstar.pq_gt_1 _ _ p_prime q_prime) ) : list bool :=
let nn := ceiling_div len 32 gt_32_0 in
let nk := ceiling_div (S (Zabs_nat (N_digits (p * q)))) 32 gt_32_0 in
let modu := p * q in
let seed' := proj1_sig seed in
match Restrictions_dec nn nk modu seed' with
| left H => firstn len
(bbs_encode_decode.Implem.decode (proj1_sig (bbs_encode_decode.Implem.exec_bbs_asm nn nk modu seed' H)))
| right _ => nil
end.
Hypothesis p_odd : Zodd p.
Hypothesis q_odd : Zodd q.
The assembly code Implem.bbs_asm implements BBS.bbs.
We need a technical lemma tech1.
Lemma bbs_semop : forall (len : nat) (seed : Zstar.Zstar (p * q) (Zstar.pq_gt_1 p q p_prime q_prime)) final_state,
let nn := ceiling_div (S len) 32 gt_32_0 in
let nk := ceiling_div (S (Zabs_nat (N_digits (p * q)))) 32 gt_32_0 in
let modu := p * q in
let seed' := proj1_sig seed in
4 * (Z_of_nat (4 * nk + nn + 2)) < 2^^32 ->
bbs_encode_decode.Implem.exec_sgoto bbs_encode_decode.Implem.bbs_asm
(Some (O, bbs_encode_decode.Implem.encode nn nk seed' modu)) (Some (240%nat, final_state)) ->
bbs_encode_decode.Implem.decode final_state =
BBS.bbs _ _ p_prime q_prime (nn * 32) seed.
Proof.
intros len seed final_state nn nk modu seed' Hny Hexec_sgoto.
rewrite (bbs_encode_decode.Implem.bbs_semop nn nk modu seed') //.
- by apply bbs_fun_bbs.
- split.
apply Zmult_lt_0_compat; [destruct p_prime | destruct q_prime]; omega.
split.
rewrite mult_comm.
by apply tech1.
split.
by apply Zodd_mult_Zodd.
split; rewrite /seed'.
* destruct seed => /=; omega.
* split => //.
rewrite /modu /=.
destruct seed => /=; omega.
Qed.
Lemma bbs_asm_sem_bbs : forall seed len,
let nn := ceiling_div (S len) 32 gt_32_0 in
let nk := ceiling_div (S (Zabs_nat (N_digits (p * q)))) 32 gt_32_0 in
4 * Z_of_nat (4 * nk + nn + 2) < 2 ^^ 32 ->
bbs_asm_sem (S len) seed = BBS.bbs p q p_prime q_prime (S len) seed.
Proof.
move=> seed len nn nk Hny.
rewrite /bbs_asm_sem.
rewrite -/nn -/nk.
case: (Restrictions_dec nn nk (p * q) (proj1_sig seed)) => Hrestr.
- idtac.
match goal with
| |- context [bbs_encode_decode.Implem.exec_bbs_asm ?a ?b ?c ?d ?e] =>
destruct (bbs_encode_decode.Implem.exec_bbs_asm a b c d e) as [final_state [Hfinal_state ?] ]
end.
rewrite (bbs_semop len seed) //.
rewrite mult_comm.
by apply firstn_bbs, le_mult_ceiling_div.
- contradict Hrestr.
split.
apply Zmult_lt_0_compat; [destruct p_prime | destruct q_prime]; omega.
split.
rewrite mult_comm.
by apply tech1.
split.
by apply Zodd_mult_Zodd.
split.
* destruct seed => /=; omega.
* split => //.
rewrite /=.
destruct seed => /=; omega.
Qed.
Under the quadratic residuosity assumption qra, the assembly code Implem.bbs_asm is
unpredictable.
Hypothesis distinct : p <> q.
Hypothesis p_blum : p mod 4 = 3 mod 4.
Hypothesis q_blum : q mod 4 = 3 mod 4.
Variable epsilon : R.
Hypothesis qra : HardProblem.QR _ _ p_prime q_prime epsilon.
Theorem unpredictable : forall len,
let nn := ceiling_div (S len) 32 gt_32_0 in
let nk := ceiling_div (S (Zabs_nat (N_digits (p * q)))) 32 gt_32_0 in
4 * Z_of_nat (4 * nk + nn + 2) < 2 ^^ 32 ->
Security.left_unpredictability _ (Zstar.Zstar_listNE _ (Zstar.pq_gt_1 _ _ p_prime q_prime)) bbs_asm_sem len epsilon.
Proof.
intros len nn nk Hny.
rewrite /Security.left_unpredictability => A.
apply: (Distribution.DistribLib.Equiv_transitive _ (fun b : bool => eqb b true) 0 epsilon
_ _ _ _ _ (BBS.unpredictable _ _ p_prime q_prime distinct p_odd q_odd p_blum q_blum _ qra len A)); last by ring.
apply Distribution.DistribLib.Equiv_extensionality => seed.
rewrite bbs_asm_sem_bbs //.
by apply Distribution.DistribLib.Equiv_reflexive.
Qed.
End BBS.