require import AllCore Int Real Distr. (** Given types for keys, plaintexts and ciphertexts **) type eK, ptxt, ctxt. (** and a leakage function (modelling the information about the plaintext that can be inferred from the ciphertext) **) type leaks. op leak: ptxt -> leaks. (* and a distribution on ciphertexts parameterized by leaks, used to specify security *) op dC: leaks -> ctxt distr. axiom dC_ll p: is_lossless (dC p). (* An encryption scheme is a triple of algorithm *) module type Enc_Scheme = { proc keygen() : eK proc enc(k:eK, p:ptxt): ctxt proc dec(k:eK, c:ctxt): ptxt option }. theory RCPA. (* IND$-CPA *) module type RCPA_Oracles = { proc enc(p:ptxt): ctxt }. module type RCPA_Adversary(O : RCPA_Oracles) = { proc distinguish() : bool }. module RCPA_Wrap (S : Enc_Scheme): RCPA_Oracles = { var k: eK proc enc(p:ptxt): ctxt = { var c; c <@ S.enc(k,p); return c; } }. module INDR_CPA (S:Enc_Scheme, A:RCPA_Adversary) = { proc main(): bool = { var b; RCPA_Wrap.k <@ S.keygen(); b <@ A(RCPA_Wrap(S)).distinguish(); return b; } }. module Ideal = { proc keygen(): eK = { return witness; } proc enc(k:eK,p:ptxt): ctxt = { var r; r <$ dC (leak p); return r; } proc dec(k:eK,p:ctxt): ptxt option = { return None; } }. (** An encryption scheme S is IND$-CPA secure if, for all * "reasonable" adversary A, the following quantity is "small": * * Adv^{IND$-CPA}_{S}(A,&m) * = `|Pr[INDR_CPA(S,A).main() @ &m: res] * - Pr[INDR_CPA(Ideal,A).main() @ &m: res]| **) end RCPA. theory PTXT. require import FSet. (* Definitions for INT-PTXT security *) module type PTXT_Oracles = { proc enc(p:ptxt) : ctxt proc verify(c:ctxt): bool }. module type PTXT_Adversary (O : PTXT_Oracles) = { proc forge(): unit }. module PTXT_Wrap (S : Enc_Scheme): PTXT_Oracles = { var k : eK var s : ptxt fset var win: bool proc init(): unit = { k <@ S.keygen(); s <- fset0; win <- false; } proc enc(p:ptxt): ctxt = { var c; c <@ S.enc(k,p); s <- s `|` (fset1 p); return c; } proc verify(c:ctxt): bool = { var p; p <@ S.dec(k,c); win <- win \/ (p <> None /\ !mem s (oget p)); return (p <> None); } }. module INT_PTXT (S : Enc_Scheme, A : PTXT_Adversary) = { proc main(): bool = { PTXT_Wrap(S).init(); A(PTXT_Wrap(S)).forge(); return PTXT_Wrap.win; } }. (* An encryption scheme E : Enc_Scheme is said to be INT-PTXT secure whenever, for all "efficient" PTXT adversary A, the following quantity is "small": Adv^{INT-PTXT}_{E}(A) = Pr[INT_PTXT(E,A).main: res] *) end PTXT. theory CTXT. require import FSet. (* Definitions for INT-CTXT security *) module type CTXT_Oracles = { proc enc(p:ptxt) : ctxt proc verify(c:ctxt): bool }. module type CTXT_Adversary (O : CTXT_Oracles) = { proc forge(): unit }. module CTXT_Wrap (S : Enc_Scheme): CTXT_Oracles = { var k : eK var s : ctxt fset var win: bool proc init(): unit = { k <@ S.keygen(); s <- fset0; win <- false; } proc enc(p:ptxt): ctxt = { var c; c <@ S.enc(k,p); s <- s `|` (fset1 c); return c; } proc verify(c:ctxt): bool = { var p; p <@ S.dec(k,c); win <- win \/ (p <> None /\ !mem s c); return (p <> None); } }. module INT_CTXT (S : Enc_Scheme, A : CTXT_Adversary) = { proc main(): bool = { CTXT_Wrap(S).init(); A(CTXT_Wrap(S)).forge(); return CTXT_Wrap.win; } }. (* An encryption scheme E : Enc_Scheme is said to be INT-CTXT secure whenever, for all "efficient" CTXT adversary A , the following quantity is "small": Adv^{INT-CTXT}_{E}(A) = Pr[INT_CTXT(E,A).main: res] *) end CTXT.