Section ElGamal.
(* Assume a finite cyclic group.   This command brings several names into the environment, including 'order' which describes the order of the group. *)
Context`{FCG : FiniteCyclicGroup}.
(* FiniteCyclicGroup is from a generic group theory library.  To use any type in FCF, equality must be decidable for that type.  Assume that equality is decidable for group elements. This fact will be located automatically when needed. *)
Hypothesis GroupElement_EqDec : EqDec GroupElement.
(* The ElGamal key generation procedure.  The notation [ .. order) is from the RndNat library, and it produces a uniformly-random natural number in the specified interval.  *)
Definition ElGamalKeygen :=
m <-$ [0 .. order);
ret (m, g^m).
(* The ElGamal encryption procedure. *)
Definition ElGamalEncrypt(msg key : GroupElement) :=
m <-$ [0 .. order);
ret (g^m, key^m * msg).
(* The ElGamal decryption procedure. *)
Definition ElGamalDecrypt(key : nat)(ct : GroupElement * GroupElement) :=
[c1, c2] <-2 ct;
s <- c1^key;
(inverse s) * c2.

(* We can prove that decryption is correct.  This procedure is deterministic, so this is just a typical Coq proof.  *)
Theorem ElGamalDecrypt_correct :
forall (pubkey msg : GroupElement)(prikey : nat)(ct : GroupElement * GroupElement),
In (prikey, pubkey) (getSupport ElGamalKeygen) ->
In ct (getSupport (ElGamalEncrypt msg pubkey)) ->
ElGamalDecrypt prikey ct = msg.