Il MAC è lì per rilevare l'alterazione dei dati che ti interessano, cioè il risultato della decrittazione. Quindi hai la seguente scelta:
- o calcoli HMAC sui dati in chiaro (cioè prima della crittografia durante la crittografia, dopo la decrittografia durante la decrittografia);
- o calcoli l'HMAC sui dati crittografati (ad esempio dopo la crittografia durante la crittografia, prima della decrittografia durante la decrittografia).
Nel secondo caso, devi includere nell'input HMAC tutto che influisce sul processo di decodifica, cioè non solo il risultato della crittografia di per sé, ma anche l'IV che è stato usato per quella crittografia, e, se il protocollo generale supporta l'agilità dell'algoritmo, dovresti anche inserire la specifica dell'algoritmo di crittografia (altrimenti, un utente malintenzionato potrebbe modificare l'intestazione del tuo messaggio per sostituire il tag che dice "AES-256" con il tag che dice "AES -128 "e decifri inconsapevolmente con l'algoritmo sbagliato)
Per sicurezza , la seconda scelta (criptare quindi MAC) è migliore; vedi questa domanda su crypto.SE per dettagli (per riassumere, quando il MAC è calcolato sui dati crittografati, non può perdere informazioni sui dati in chiaro, e poiché è verificato prima di tentare la decifrazione, protegge dagli attacchi di testo cifrato scelti). SSL utilizza MAC-then-encrypt ed è stato fonte di molti problemi (tutti gli "attacchi oracle di padding" e anche il cosiddetto attacco BEAST sarebbe stato evitato con encrypt-then-MAC).
Per quanto riguarda le chiavi, idealmente, la chiave di crittografia e la chiave MAC dovrebbero essere derivate da una chiave principale con un PRF . In parole semplici: hash la tua chiave principale K con SHA-512; la prima metà del risultato sarà la chiave di crittografia, la seconda metà sarà la chiave per HMAC.
Tuttavia, dovresti utilizzare EAX o GCM . Fanno tutto correttamente e (questo è un punto importante) hanno requisiti molto chiari sulla selezione IV: hanno solo bisogno di un IV non ripetuto, quindi possono usare un contatore semplice, mentre il CTR fatto a mano ha bisogno di intervalli IV non sovrapposti (una IV con selezione casuale uniforme è corretta, ma la casualità è un requisito difficile) (e CBC è anche peggio, ha bisogno di casualità imprevedibile ). L'unica giustificazione per non usando EAX o GCM in un nuovo sistema (dove non si è vincolati alla retrocompatibilità) è una possibile non disponibilità di un'implementazione EAX o GCM. Direi che, anche in questo caso, sarebbe meglio riadattare un codice AES-ECB in un'implementazione EAX.