(** The inversion of an operator. *)
Definition inv_op (o : op) : op :=
  match o with
  | Pub => Priv
  | Priv => Pub
  | _ => o
  end.(** A message is either a name, or an encrypted message, 
    or a pair of messages, or an operator applied to a message. *)
Inductive Msg : Set :=
  | MNam : Nam -> Msg
  | MEnc : Msg -> Msg -> Msg
  | MPair : Msg -> Msg -> Msg
  | Mop : op -> Msg -> Msg.(** A message is either a name, or an encrypted message, 
    or a pair of messages, or an operator applied to a message. *)
Inductive Msg : Set :=
  | MNam : Nam -> Msg
  | MEnc : Msg -> Msg -> Msg
  | MPair : Msg -> Msg -> Msg
  | Mop : op -> Msg -> Msg.(** A message is either a name, or an encrypted message, 
    or a pair of messages, or an operator applied to a message. *)
Inductive Msg : Set :=
  | MNam : Nam -> Msg
  | MEnc : Msg -> Msg -> Msg
  | MPair : Msg -> Msg -> Msg
  | Mop : op -> Msg -> Msg.(** A message is either a name, or an encrypted message, 
    or a pair of messages, or an operator applied to a message. *)
Inductive Msg : Set :=
  | MNam : Nam -> Msg
  | MEnc : Msg -> Msg -> Msg
  | MPair : Msg -> Msg -> Msg
  | Mop : op -> Msg -> Msg.(** A message is either a name, or an encrypted message, 
    or a pair of messages, or an operator applied to a message. *)
Inductive Msg : Set :=
  | MNam : Nam -> Msg
  | MEnc : Msg -> Msg -> Msg
  | MPair : Msg -> Msg -> Msg
  | Mop : op -> Msg -> Msg.(** Inversion of a message. This is to manage public/private keys. *)
Definition inv (M : Msg) : Msg :=
  match M with
  | Mop op M => Mop (inv_op op) M
  | _ => M
  end.

(* Specifications: *)
Lemma inv_invol : forall M : Msg, inv (inv M) = M.