https://github.com/EasyCrypt/easycrypt
Tip revision: 9b906a364f732efd3b8a29f5316c0fd22ede833c authored by Pierre-Yves Strub on 10 February 2020, 09:45:49 UTC
Merge branch '1.0' into deploy-lamport
Merge branch '1.0' into deploy-lamport
Tip revision: 9b906a3
FDH.ec
require import Fun.
require import Bool.
require import Int.
require import Real.
require import FSet.
require import ISet.
import Finite.
require import Map.
require import Pair.
(*** General definitions *)
(** Lengths *)
op k:int.
axiom leq0_k: 0 < k.
op qS:int.
axiom leq0_qS: 0 <= qS.
op qH:int.
axiom leq0_qH: 0 <= qH.
(** Types *)
require AWord.
require import ABitstring.
type message = bitstring.
(* Signatures *)
type signature.
clone import AWord as Signature with
type word <- signature,
op length <- k.
op s_signature (x:message) = Signature.Dword.dword.
(* Domain of RSA *)
op sample_plain: signature distr. (* Whereby we sample only with the first byte/bit set to 0 *)
(** Instantiating *)
require PKS.
require OW.
require RandomOracle.
type pkey.
op challenge (pk:pkey) = sample_plain.
clone import OW as RSA with
type t <- signature,
type pkey <- pkey,
op challenge <- challenge.
clone import RandomOracle.Lazy as Ht with
type from <- message,
type to <- signature,
op dsample <- s_signature.
import Types.
module H = RO.
clone import PKS as PKSi with
type pkey <- pkey,
type skey <- skey,
type message <- message,
type signature <- signature.
import EF_CMA.
module FDH(H:Oracle): Scheme = {
fun init(): unit = {
H.init();
}
fun keygen(): pkey * skey = {
var (pk,sk): pkey * skey;
(pk,sk) = $keypairs;
return (pk,sk);
}
fun sign(sk:skey, m:message): signature = {
var h:signature;
h = H.o(m);
return finv sk h;
}
fun verify(pk:pkey, m:message, s:signature): bool = {
var h:signature;
h = H.o(m);
return h = f pk s;
}
}.
module type CMA_ROM(H:ARO,O:AdvOracles) = {
fun forge(pk:pkey): message * signature
}.
module type FDHOracles = {
fun init(): pkey {*}
fun sign(m:message): signature
fun fresh(m:message): bool
}.
(** Partially Inlined Oracles for G0 and G1 **)
module FDH_O(H:Oracle): FDHOracles = {
var pk:pkey
var sk:skey
var qs:message FSet.set
fun init(): pkey = {
H.init();
qs = FSet.empty;
(pk,sk) = $keypairs;
return pk;
}
fun sign(m:message): signature = {
var h:signature;
qs = add m qs;
h = H.o(m);
return finv sk h;
}
fun fresh(m:message): bool = {
return !mem m qs;
}
}.
(** G0: Inlining the verification algorithm *)
module G0(Adv:AdvCMA) = {
module O = FDH_O(H)
module A = Adv(O)
fun main(): bool = {
var pk:pkey;
var m:message;
var s, h:signature;
var fresh:bool;
pk = O.init();
(m,s) = A.forge(pk);
h = H.o(m);
fresh = O.fresh(m);
return h = f pk s /\ fresh;
}
}.
equiv FDH_G0_equiv (A <: CMA_ROM {H, Number, Wrap, FDH_O}):
EF_CMA(Wrap(FDH(H)),A(H)).main ~ G0(A(Number(H))).main:
={glob A} ==> ={res}.
proof strict.
fun.
call (_: ={m} /\
Wrap.qs{1} = FDH_O.qs{2} ==>
={res});
first by fun; wp.
inline Wrap(FDH(ROM.RO)).verify FDH(ROM.RO).verify; wp.
call (_: ={glob H});
first by eqobs_in.
wp.
call (_: ={glob H} /\
Wrap.pk{1} = FDH_O.pk{2} /\
Wrap.sk{1} = FDH_O.sk{2} /\
Wrap.qs{1} = FDH_O.qs{2}).
fun; inline FDH(ROM.RO).sign; wp;
call (_: ={glob H}); first by eqobs_in.
by wp.
fun*; inline Number(ROM.RO).o; wp;
call (_: ={glob H}); first by eqobs_in.
by wp.
call (_: true ==>
={res, glob H} /\
Wrap.pk{1} = res{1} /\
Wrap.pk{1} = FDH_O.pk{2} /\
Wrap.sk{1} = FDH_O.sk{2} /\
Wrap.qs{1} = FDH_O.qs{2})=> //.
fun; inline FDH(ROM.RO).keygen FDH(ROM.RO).init;
wp; rnd; wp;
call (_: true ==> ={glob H})=> //;
first by fun; eqobs_in.
qed.
(** G1: Indexing the random oracle and setting things up *)
module G1(Adv:AdvCMA) = {
module O = FDH_O(Number(H))
module A = Adv(O)
var m:message
var t:(int,bool) map
fun main(): bool = {
var pk:pkey;
var s,h:signature;
var forged:bool;
var i:int;
pk = O.init();
i = 0;
(m,s) = A.forge(pk);
h = H.o(m);
forged = (h = f pk s);
while (i < qH)
{
t.[i] = ${0,1};
i = i + 1;
}
return forged;
}
}.
lemma G0_G1_equiv (A <: CMA_ROM {H, Number, FDH_O}):
equiv [G0(A(H)).main ~ G1(A(Number(H))).main:
={glob A} ==>
res{1} = (res /\ !mem G1.m FDH_O.qs){2}].
proof strict.
fun.
seq 3 4: (={pk, h, s, glob H, glob FDH_O} /\
m{1} = G1.m{2} /\
i{2} <= qH); first last.
while{2} true (qH - i{2});
first progress=> //; wp; rnd; first by apply Dbool.lossless.
by skip; smt.
inline G0(A(ROM.RO)).O.fresh; wp; skip; smt.
call (_: ={glob H}); first by eqobs_in.
call (_: ={glob H, glob FDH_O}).
fun; inline Number(ROM.RO).o; wp;
call (_: ={glob H}); first by eqobs_in.
by wp.
fun*; inline Number(ROM.RO).o; wp;
call (_: ={glob H}); first by eqobs_in.
by wp.
wp.
call (_: true ==>
={glob H, glob FDH_O, res}).
fun; inline Number(ROM.RO).init; eqobs_in.
skip; progress=> //; smt.
qed.