Din motive vechi, unul dintre sistemele mele nu are opțiunea de a folosi un mod AEAD, suntem restricționați la AES în modul simplu CBC sau CTR plus un MAC.
O sarcină tipică este transferul datelor de la un nod la altul, garantând în același timp integritatea și confidențialitatea. Mă trezesc să precizez în mod repetat următoarea compoziție:
- CSPRNG pentru a genera un secret bootstrap
- KDF pentru a obține chei pentru criptare și MAC - folosesc HKDF
- CSPRNG din nou obține un iv
- Modul CTR pentru a cripta datele
- MAC peste bootstrap secret, iv, cipherspec și ciphertext - folosesc HMAC
Deci fac Encrypt-then-MAC și autentific toate intrările la calculul ciphertext. Dar am presupus cu bucurie că această compoziție este sigură.
Nu am văzut niciodată această compoziție completă, inclusiv KDF descrisă ca o primitivă reutilizabilă.
TLS face ceva foarte asemănător, dar nu este chiar același (de exemplu, folosește HKDF diferit).
Schemele IES precum ECIES și DLIES arată conceptual similar, dar diferă în detalii, în special în modul în care sunt derivate intrările către KDF.
Deci întrebarea mea este: această problemă este insuficient de generală pentru a justifica o soluție de carte de bucate? Sau poate că există deja ceva pe care l-am trecut cu vederea? Altfel, cum pot câștiga încredere în soluție? (Când vine vorba de cripto, sunt întotdeauna precaut).
În cazul în care detaliile sunt utile, fluxul este:
Nodul de trimitere efectuează următoarele:
- Obțineți 256 de biți secreti
sămânță
dintr-un CSPRNG
- Criptează
sămânță
pentru celălalt nod folosind cheia publică ca semințe_criptate
- Despică
sămânță
în 128 de biți sare
și 128 de biți material_cheie
- Deduceți 384 de biți secreti prin apelare
HKDF-HMAC-SHA-256(lungime=384b, ikm=key_material, sare=sare, info=<id nod sursă || id nod dest>)
- Împărțit în 128 de biți
cheie_criptare
, 256 de biți HMAC_key
Pentru fiecare mesaj de trimis:
- Obțineți 128 de biți de la un CSPRNG ca
criptare_iv
- Criptați textul simplu folosind
AES-128-CTR(iv=encryption_iv, cheie=encryption_key)
- Calculați eticheta ca
HMAC-SHA-256(key=HMAC_key, data=encrypted_seed || encryption_iv || cipherspec=AES-128-CTR || ciphertext)
- Trimite la celălalt nod:
semințe_criptate || criptare_iv || cipherspec || text cifrat || etichetă
Nodul receptor efectuează următoarele:
- Analizați mesajul primit în componentele sale
semințe_criptate
etc.
- Decriptează
semințe_criptate
folosind cheia privată a nodului receptor, obținând sămânță
- Despică
sămânță
în 128 de biți sare
și 128 de biți material_cheie
- Deduceți 384 de biți secreti prin apelare
HKDF-HMAC-SHA-256(lungime=384b, ikm=key_material, sare=sare, info=<id nod sursă || id nod dest>)
- Împărțit în 128 de biți
cheie_criptare
, 256 de biți HMAC_key
- Calculați eticheta ca
HMAC-SHA-256(key=HMAC_key, data=<mesajul primit de la nodul expeditor fără etichetă>)
- Atribui
tag_valid := adevărat
dacă eticheta se potrivește cu cea de pe mesajul primit, fals
in caz contrar
- Atribui
k := cheie_criptare
dacă tag_valid
, altfel atribuiți k := <o constantă aleatorie>
- Decriptați textul cifrat ca
[cipherspec](iv=criptare_iv, cheie=k)
- Ieșiți un tuplu
(tag_valid, text simplu)
- apelantul este responsabil să verifice tag_valid
înainte de a utiliza text simplu
Deci ce ar putea merge prost? Ei bine, pentru unul sămânță
valoarea este utilizată înainte ca eticheta MAC să fie verificată. L-aș putea semna folosind cheia privată a nodului de trimitere, dar asta nu se leagă de fapt sămânță
la eticheta MAC. De asemenea, asta începe să devină dezordonat, de unde neliniștea mea.