Theory Elgamal
section βΉCryptographic constructions and their securityβΊ
theory Elgamal imports
CryptHOL.Cyclic_Group_SPMF
CryptHOL.Computational_Model
Diffie_Hellman
IND_CPA_PK_Single
CryptHOL.Negligible
begin
subsection βΉElgamal encryption schemeβΊ
locale elgamal_base =
fixes π’ :: "'grp cyclic_group" (structure)
begin
type_synonym 'grp' pub_key = "'grp'"
type_synonym 'grp' priv_key = nat
type_synonym 'grp' plain = 'grp'
type_synonym 'grp' cipher = "'grp' Γ 'grp'"
definition key_gen :: "('grp pub_key Γ 'grp priv_key) spmf"
where
"key_gen = do {
x β sample_uniform (order π’);
return_spmf (βg [^] x, x)
}"
lemma key_gen_alt:
"key_gen = map_spmf (Ξ»x. (βg [^] x, x)) (sample_uniform (order π’))"
by(simp add: map_spmf_conv_bind_spmf key_gen_def)
definition aencrypt :: "'grp pub_key β 'grp β 'grp cipher spmf"
where
"aencrypt Ξ± msg = do {
y β sample_uniform (order π’);
return_spmf (βg [^] y, (Ξ± [^] y) β msg)
}"
lemma aencrypt_alt:
"aencrypt Ξ± msg = map_spmf (Ξ»y. (βg [^] y, (Ξ± [^] y) β msg)) (sample_uniform (order π’))"
by(simp add: map_spmf_conv_bind_spmf aencrypt_def)
definition adecrypt :: "'grp priv_key β 'grp cipher β 'grp option"
where
"adecrypt x = (Ξ»(Ξ², ΞΆ). Some (ΞΆ β (inv (Ξ² [^] x))))"
abbreviation valid_plains :: "'grp β 'grp β bool"
where "valid_plains msg1 msg2 β‘ msg1 β carrier π’ β§ msg2 β carrier π’"
sublocale ind_cpa: ind_cpa key_gen aencrypt adecrypt valid_plains .
sublocale ddh: ddh π’ .
fun elgamal_adversary :: "('grp pub_key, 'grp plain, 'grp cipher, 'state) ind_cpa.adversary β 'grp ddh.adversary"
where
"elgamal_adversary (π1, π2) Ξ± Ξ² Ξ³ = TRY do {
b β coin_spmf;
((msg1, msg2), Ο) β π1 Ξ±;
_ :: unit β assert_spmf (valid_plains msg1 msg2);
guess β π2 (Ξ², Ξ³ β (if b then msg1 else msg2)) Ο;
return_spmf (guess = b)
} ELSE coin_spmf"
end
locale elgamal = elgamal_base + cyclic_group π’
begin
theorem advantage_elgamal: "ind_cpa.advantage π = ddh.advantage (elgamal_adversary π)"
including monad_normalisation
proof -
obtain π1 and π2 where "π = (π1, π2)" by(cases π)
note [simp] = this order_gt_0_iff_finite finite_carrier try_spmf_bind_out split_def o_def spmf_of_set bind_map_spmf weight_spmf_le_1 scale_bind_spmf bind_spmf_const
and [cong] = bind_spmf_cong_simp
have "ddh.ddh_1 (elgamal_adversary π) = TRY do {
x β sample_uniform (order π’);
y β sample_uniform (order π’);
((msg1, msg2), Ο) β π1 (βg [^] x);
_ :: unit β assert_spmf (valid_plains msg1 msg2);
b β coin_spmf;
z β map_spmf (Ξ»z. βg [^] z β (if b then msg1 else msg2)) (sample_uniform (order π’));
guess β π2 (βg [^] y, z) Ο;
return_spmf (guess β· b)
} ELSE coin_spmf"
by(simp add: ddh.ddh_1_def)
also have "β¦ = TRY do {
x β sample_uniform (order π’);
y β sample_uniform (order π’);
((msg1, msg2), Ο) β π1 (βg [^] x);
_ :: unit β assert_spmf (valid_plains msg1 msg2);
z β map_spmf (Ξ»z. βg [^] z) (sample_uniform (order π’));
guess β π2 (βg [^] y, z) Ο;
map_spmf ((=) guess) coin_spmf
} ELSE coin_spmf"
by(simp add: sample_uniform_one_time_pad map_spmf_conv_bind_spmf[where p=coin_spmf])
also have "β¦ = coin_spmf"
by(simp add: map_eq_const_coin_spmf try_bind_spmf_lossless2')
also have "ddh.ddh_0 (elgamal_adversary π) = ind_cpa.ind_cpa π"
by(simp add: ddh.ddh_0_def IND_CPA_PK_Single.ind_cpa.ind_cpa_def key_gen_def aencrypt_def nat_pow_pow eq_commute)
ultimately show ?thesis by(simp add: ddh.advantage_def ind_cpa.advantage_def)
qed
end
locale elgamal_asymp =
fixes π’ :: "security β 'grp cyclic_group"
assumes elgamal: "βΞ·. elgamal (π’ Ξ·)"
begin
sublocale elgamal "π’ Ξ·" for Ξ· by(simp add: elgamal)
theorem elgamal_secure:
"negligible (λη. ind_cpa.advantage Ξ· (π Ξ·))" if "negligible (λη. ddh.advantage Ξ· (elgamal_adversary Ξ· (π Ξ·)))"
by(simp add: advantage_elgamal that)
end
context elgamal_base begin
lemma lossless_key_gen [simp]: "lossless_spmf (key_gen) β· 0 < order π’"
by(simp add: key_gen_def Let_def)
lemma lossless_aencrypt [simp]:
"lossless_spmf (aencrypt key plain) β· 0 < order π’"
by(simp add: aencrypt_def Let_def)
lemma lossless_elgamal_adversary:
"β¦ ind_cpa.lossless π; 0 < order π’ β§
βΉ ddh.lossless (elgamal_adversary π)"
by(cases π)(simp add: ddh.lossless_def ind_cpa.lossless_def Let_def split_def)
end
end