Dacă datele pe care vreau să le autentific constă din mai multe valori și calculez un MAC pur și simplu concatenând valorile, un adversar poate „schimba” caracterele în acele valori fără a invalida MAC-ul. Cum este această problemă frecvent și cel mai bine abordată?
Am gasit această întrebare existentă despre MACing mai multe mesaje, dar simt că soluțiile propuse nu se generalizează bine pentru mai mult de două mesaje.
Luați în considerare următorul exemplu artificial:
Să presupunem că am un server care stochează intrări de jurnal autentice pentru clienți. Clientul scrie o intrare de jurnal, o autentifică folosind un MAC și o trimite la server. Mai târziu, când clientul preia intrările de jurnal de pe server, ar trebui să poată verifica autenticitatea acestora.
Să presupunem că intrările de jurnal au următoarea structură:
{
creat la: "1621012345",
mesaj: „prima intrare”
}
Naiv, aș putea crea un MAC pentru o intrare de jurnal l
la fel de
$$
mac = \text{HMAC}(K, l.createdAt \| l.message)
$$
Unde $\|$ denotă concatenare şi $K$ este cheia secretă.
Dacă ar fi să stochez această intrare de jurnal și MAC pe un server și să o recuperez mai târziu, serverul ar putea reveni
{
creat la: "1621012",
mesaj: „345prima intrare”,
mac: „<MAC-ul calculat mai sus>”
}
De cand 1621012 || 345prima intrare
este la fel ca 1621012345 || prima intrare
Nu aș observa manipularea la verificarea MAC-ului.
Rețineți că, în acest caz, ar trebui să detectez de fapt manipularea validând apoi lungimea creat la
. Dar asta funcționează doar dacă lungimea este fixă și nu dacă aș avea, să zicem, numele autorului
în loc de marcajul de timp.
Mă pot gândi la următoarele moduri de a trata acest lucru:
1. Intercalați un delimitator
Dacă mi-am calculat MAC ca $mac = \text{HMAC}(K, l.createdAt \| \text{':'} \| l.message)$ Cred că acest atac nu ar mai fi posibil. La prima vedere pare problematic faptul că caracterul delimitator poate apărea în mesaj. Dar asta face doar imposibilă reconstruirea fără ambiguitate a valorilor din șirul concatenat, ceea ce este irelevant în acest scenariu. Nu mă pot gândi la vreo modalitate de a face calculul MAC ambiguu aici. Este sigură această soluție simplă?
2. Valori hash înainte de concatenare
Aș putea calcula MAC-ul, de exemplu, ca $mac = \text{HMAC}(K, \text{SHA256}(l.createdAt) \| \text{SHA256}(l.message))$ (sau orice altă funcție hash criptografică). Acest lucru asigură că un adversar nu poate manipula în mod semnificativ valorile pe care le concatenez. De asemenea, se asigură că valorile concatenate au întotdeauna o lungime fixă. Hashing-ul adaugă vreo valoare în comparație cu prima idee?
3. Autentificați toate datele structurate
De asemenea, aș putea calcula MAC-ul peste obiectul JSON complet al intrării de jurnal. În mod efectiv, asta înseamnă că am delimitatori mai elaborați și semnificativi (cheile și sintaxa). Practic, ca un JWT.
Rețineți că această abordare are și unele dezavantaje, care se rezumă în principal la pierderea flexibilității API și la necesitatea de a canoniza JSON. Există o postare grozavă pe blog despre asta la https://latacora.micro.blog/2019/07/24/how-not-to.html.
Îmi lipsesc vreo soluție bună pentru această problemă? Există o modalitate recomandată de a face față acestui lucru?