Theory MLWE
theory MLWE
imports Lemmas_for_spmf
"Game_Based_Crypto.CryptHOL_Tutorial"
begin
section ‹Module Learning-with-Errors Problem (module-LWE)›
text ‹‹Berlekamp_Zassenhaus› loads the vector type ‹'a vec› from ‹Jordan_Normal_Form.Matrix›.
This doubles the symbols ‹\$› and ‹χ› for ‹vec_nth› and ‹vec_lambda›. Thus we delete the
‹vec_index› for type ‹'a vec›. Still some type ambiguities remain.›
unbundle %invisible lifting_syntax
no_adhoc_overloading %invisible Monad_Syntax.bind bind_pmf
declare %invisible [[names_short]]
text ‹Here the actual theory starts.›
text ‹We introduce a locale ‹module_lwe› that represents the module-Learning-with-Errors
(module-LWE) problem in the setting of Kyber.
The locale takes as input:
\begin{itemize}
\item ‹type_a› the type of the quotient ring of Kyber. (This is a side effect of the Harrison
trick in the Kyber locale.)
\item ‹type_k› the finite type for indexing vectors in Kyber. The cardinality is exactely $k$.
(This is a side effect of the Harrison trick in the Kyber locale.)
\item ‹idx› an indexing function from ‹'k› to ‹{0..<k}›
\item ‹eta› the specification value for the centered binomial distribution $\beta_\eta$
\end{itemize}›
locale module_lwe =
fixes type_a :: "('a :: qr_spec) itself"
and type_k :: "('k ::finite) itself"
and k :: nat
and idx :: "'k::finite ⇒ nat"
and eta :: nat
assumes "k = CARD('k)"
and bij_idx: "bij_betw idx (UNIV::'k set) {0..<k}"
begin
text ‹The adversary in the module-LWE takes a matrix ‹A::(('b, 'n) vec, 'm) vec› and a vector
‹t::('b, 'm) vec› and returns a probability distribution on ‹bool›
guessing whether the given input was randomly generated or a valid module-LWE instance.›
type_synonym ('b, 'n, 'm) adversary =
"(('b, 'n) vec, 'm) vec ⇒ ('b, 'm) vec ⇒ bool spmf"
text ‹Next, we want to define the centered binomial distributions $\beta_\eta$.
‹bit_set› returns the set of all bit lists of length ‹eta›.
‹beta› is the centered binomial distribution $\beta_\eta$ as a ‹pmf› on the quotient ring $R_q$.
‹beta_vec› is then centered binomial distribution $\beta_\eta ^k$ on vectors in $R_q^k$.›
definition bit_set :: "int list set" where
"bit_set = {xs:: int list. set xs ⊆ {0,1} ∧ length xs = eta}"
lemma finite_bit_set:
"finite bit_set"
unfolding bit_set_def
by (simp add: finite_lists_length_eq)
lemma bit_set_nonempty:
"bit_set ≠ {}"
proof -
have "replicate eta 0 ∈ bit_set" unfolding bit_set_def by auto
then show ?thesis by auto
qed
adhoc_overloading %invisible Monad_Syntax.bind bind_pmf
definition beta :: "'a qr pmf" where
"beta = do {
as ← pmf_of_set (bit_set);
bs ← pmf_of_set (bit_set);
return_pmf (to_module (∑i<eta. as ! i - bs! i))
} "
definition beta_vec :: "('a qr , 'k) vec pmf" where
"beta_vec = do {
(xs :: 'a qr list) ← replicate_pmf (k) (beta);
return_pmf (χ i. xs ! (idx i))
}"
text ‹Since we work over ‹spmf›, we need to show that ‹beta_vec› is lossless.›
lemma lossless_beta_vec[simp]:
"lossless_spmf (spmf_of_pmf beta_vec)"
by (simp)
text ‹We define the game versions of module-LWE.
Given an adversary ‹𝒜›, we have two games:
in ‹game›, the instance given to the adversary is a module-LWE instance,
whereas in ‹game_random›, the instance is chosen randomly.›
definition game :: "('a qr,'k,'k) adversary ⇒ bool spmf" where
"game 𝒜 = do {
A ← spmf_of_set (UNIV:: (('a qr, 'k) vec, 'k) vec set);
s ← beta_vec;
e ← beta_vec;
b' ← 𝒜 A (A *v s + e);
return_spmf (b')
}"
definition game_random :: "('a qr,'k,'k) adversary ⇒ bool spmf" where
"game_random 𝒜 = do {
A ← spmf_of_set (UNIV:: (('a qr, 'k) vec, 'k) vec set);
b ← spmf_of_set (UNIV:: ('a qr, 'k) vec set);
b' ← 𝒜 A b;
return_spmf (b')
}"
text ‹The advantage of an adversary ‹𝒜› returns a value how good the adversary is at guessing
whether the instance is generated by the module-LWE or uniformly at random.›
definition advantage :: "('a qr,'k,'k) adversary ⇒ real" where
"advantage 𝒜 = ¦spmf (game 𝒜) True - spmf (game_random 𝒜) True ¦"
text ‹Since the reduction proof of Kyber uses the module-LWE problem for two different dimensions
(ie.\ $A\in R_q^{(k+1)\times k}$ and $A\in R_q^{k\times k}$), we need a second definition of
the index function, the centered binomial distribution, the game and random game, and the advantage.
Here the problem is that the dimension $k$ of the vectors is hard-coded in the type ‹'k›.
That makes it hard to ``simply add'' another dimension. A trick how this can be formalised
nevertheless is to use the option type on ‹'k› to encode a type with $k+1$ elements.
With the option type, we can embed a vector of dimension $k$ indexed by the type ‹'k› into
a vector of dimension $k+1$ by adding a value for the index ‹None› (an element ‹a :: 'k›
is mapped to ‹Some a›).
Note also that the additional index appears only in one dimension of $A$, resulting in
a non-quadratic matrix.›
text ‹Index function of the option type ‹'k option›.›
fun idx' :: "'k option ⇒ nat" where
"idx' None = 0" |
"idx' (Some x) = idx x + 1"
lemma idx': "((x # xs) ! idx' i) =
( if i = None then x else xs ! idx (the i))"
if "length xs = k" for xs and i::"'k option"
proof (cases i)
case None
then show ?thesis using nth_append_length[of xs x "[]"] that by (simp add: if_distrib)
next
case (Some a)
have "idx a < k" using bij_idx
by (meson UNIV_I atLeastLessThan_iff bij_betwE)
then show ?thesis using Some that by (simp add: if_distrib nth_append)
qed
lemma idx'_lambda:
"(χ i. (x # xs) ! idx' i) =
(χ i. if i = None then x else xs ! idx (the i))"
if "length xs = k" for xs using idx'[OF that]
by presburger
text ‹Definition of the centered binomial distribution $\beta_\eta^{k+1}$ and lossless property.›
definition beta_vec' :: "('a qr , 'k option) vec spmf" where
"beta_vec' = do {
(xs :: 'a qr list) ← replicate_spmf (k+1) (beta);
return_spmf (χ i. xs ! (idx' i))
}"
lemma lossless_beta_vec'[simp]:
"lossless_spmf beta_vec'"
unfolding beta_vec'_def beta_def
by (simp add: replicate_spmf_def)
text ‹Some lemmas on replicate.›
lemma replicate_pmf_same_length:
assumes "⋀ xs. length xs = m ⟹ f xs = g xs"
shows "bind_pmf (replicate_pmf m p) f = bind_pmf (replicate_pmf m p) g"
by (metis (mono_tags, lifting) assms bind_pmf_cong mem_Collect_eq set_replicate_pmf)
lemma replicate_spmf_same_length:
assumes "⋀ xs. length xs = m ⟹ f xs = g xs"
shows "(replicate_spmf m p ⤜ f) = (replicate_spmf m p ⤜ g)"
unfolding replicate_spmf_def bind_spmf_of_pmf
by (simp add: replicate_pmf_same_length[OF assms])
text ‹Lemma to split the ‹replicate (k+1)› function in ‹beta_vec'› into two parts:
‹replicate k› and a separate value. Note, that the ‹xs› in the ‹do› notation below are
always of length $k$. ›
no_adhoc_overloading Monad_Syntax.bind bind_pmf
lemma beta_vec':
"beta_vec' = do {
(xs :: 'a qr list) ← replicate_spmf (k) (beta);
(x :: 'a qr) ← spmf_of_pmf beta;
return_spmf (χ i. if i = None then x else xs ! (idx (the i)))
}"
unfolding beta_vec'_def idx'_lambda[symmetric] replicate_spmf_Suc_cons
bind_spmf_assoc return_bind_spmf
by (subst replicate_spmf_same_length[where
f = "(λy. spmf_of_pmf beta ⤜ (λya. return_spmf (vec_lambda (λi. (ya # y) ! idx' i))))" and
g = "(λxs. spmf_of_pmf beta ⤜ (λx. return_spmf (vec_lambda (λi. if i = None then x else
xs ! idx (the i)))))"])
(simp_all add: idx'_lambda)
adhoc_overloading Monad_Syntax.bind bind_pmf
text ‹Definition of the two games for the option type.›
definition game' :: "('a qr,'k,'k option) adversary ⇒ bool spmf" where
"game' 𝒜 = do {
A ← spmf_of_set (UNIV:: (('a qr, 'k) vec, 'k option) vec set);
s ← beta_vec;
e ← beta_vec';
b' ← 𝒜 A (A *v s + e);
return_spmf (b')
}"
definition game_random' :: "('a qr,'k,'k option) adversary ⇒ bool spmf" where
"game_random' 𝒜 = do {
A ← spmf_of_set (UNIV:: (('a qr, 'k) vec, 'k option) vec set);
b ← spmf_of_set (UNIV:: ('a qr, 'k option) vec set);
b' ← 𝒜 A b;
return_spmf (b')
}"
text ‹Definition of the advantage for the option type.›
definition advantage' :: "('a qr,'k,'k option) adversary ⇒ real" where
"advantage' 𝒜 = ¦spmf (game' 𝒜) True - spmf (game_random' 𝒜) True ¦"
text ‹Game and random game for finite type with one element only›
definition beta1 :: "('a qr , 1) vec pmf" where
"beta1 = bind_pmf beta (λx. return_pmf (χ i. x))"
definition game1 :: "('a qr, 1, 1) adversary ⇒ bool spmf" where
"game1 𝒜 = do {
A ← spmf_of_set (UNIV:: (('a qr, 1) vec, 1) vec set);
s ← spmf_of_pmf beta1;
e ← spmf_of_pmf beta1;
b' ← 𝒜 A (A *v s + e);
return_spmf (b')
}"
definition game_random1 :: "('a qr,1,1) adversary ⇒ bool spmf" where
"game_random1 𝒜 = do {
A ← spmf_of_set (UNIV:: (('a qr, 1) vec, 1) vec set);
b ← spmf_of_set (UNIV:: ('a qr, 1) vec set);
b' ← 𝒜 A b;
return_spmf (b')
}"
text ‹The advantage of an adversary ‹𝒜› returns a value how good the adversary is at guessing
whether the instance is generated by the module-LWE or uniformly at random.›
definition advantage1 :: "('a qr,1,1) adversary ⇒ real" where
"advantage1 𝒜 = ¦spmf (game1 𝒜) True - spmf (game_random1 𝒜) True ¦"
end
end