Definition b := (c+p)%nat.(* The iteration of the compression function gives a keyed hash function on lists of words. *)
  Definition h_star k (m : list (Blist)) :=
    fold_left h m k.(* The composition of the keyed hash function with the IV. *)
  Definition hash_words := h_star iv.Definition app_fpad (x : Blist) : Blist :=
    x ++ fpad x.Definition h_star_pad k x :=
    app_fpad (h_star k x).(* The "two-key" version of GHMAC and HMAC. *)
  Definition GHMAC_2K (k : Blist) m :=
    let (k_Out, k_In) := splitList b k in
      let h_in := (hash_words (k_In :: m)) in
        hash_words (k_Out :: (app_fpad h_in) :: nil).Definition HMAC_2K (k : Blist) (m : Blist) :=
    GHMAC_2K k (splitAndPad m).Definition HMAC (k : Blist) :=
    HMAC_2K (BLxor k opad ++ BLxor k ipad).

(* Specifications: *)
Lemma fpad_list_concat_eq : HMAC_List.app_fpad = HMAC_Concat.app_fpad.
Theorem HMAC_list_concat c p B fpad (fpad_length: forall msg, length msg = c -> length (fpad msg) = p) sap (sap_b: forall m, Forall (fun x => length x = (c+p)%nat) (sap m)) sap' (sap_sap': forall m, sap' m = concat (sap m)) h (HH: forall x y, length x = c -> length y = (c+p)%nat -> length (h x y) = c) iv (IV: length iv = c) (op ip : Blist) (IL: length ip = (c+p)%nat) (OL: length op = (c+p)%nat) (FOLD_hash_blocks_eq : forall (l : Blist) (ls : list Blist), length l = (c+p)%nat -> Forall (fun x : list bool => length x = (c+p)%nat) ls -> fold_left h (l :: ls) iv = hash_blocks_bits _ B h iv (l ++ concat ls)) : forall (k m : Blist), length k = (c+p)%nat -> HMAC_List.HMAC c p h iv sap fpad op ip k m = HMAC_Concat.HMAC c p B h iv sap' fpad op ip k m.