10. Considerazioni di sicurezza
Questa sezione contiene considerazioni di sicurezza aggiuntive riguardo ai meccanismi di hash-to-curve descritti in questo documento.
10.1. Proprietà delle codifiche
Ciascun tipo di codifica (Sezione 3) accetta una stringa di byte arbitraria e la mappa in un punto sulla curva campionato da una distribuzione che dipende dal tipo di codifica. È importante notare che l'uso di una codifica non uniforme o la valutazione diretta di uno dei mapping della Sezione 6 produce un output facilmente distinguibile da un punto uniformemente casuale. Le applicazioni che utilizzano una codifica non uniforme DOVREBBERO analizzare attentamente le implicazioni di sicurezza della non uniformità. Quando la codifica richiesta non è chiara, le applicazioni DOVREBBERO utilizzare una codifica uniforme.
Entrambe le codifiche date nella Sezione 3 possono emettere l'elemento identità del gruppo G. La probabilità che ciascuna delle due funzioni di codifica emetta l'elemento identità è approssimativamente 1/r per un input casuale, il che è trascurabile per curve ellittiche crittograficamente utili. Inoltre, è computazionalmente impossibile trovare un input per una delle due funzioni di codifica il cui output corrispondente sia l'elemento identità. (Entrambe queste proprietà valgono quando le funzioni di codifica sono istanziate con una funzione hash_to_field che segue tutte le linee guida della Sezione 5.) I protocolli che utilizzano queste funzioni di codifica NON DOVREBBERO aggiungere un caso speciale per rilevare e "correggere" l'elemento identità.
Quando la funzione hash_to_curve (Sezione 3) è istanziata con una funzione hash_to_field indifferenziabile da un random oracle (Sezione 5), la funzione risultante è indifferenziabile da un random oracle ([MRH04] [BCIMRT10] [FFSTV13] [LBB19] [H20]). In molti casi, tale funzione può essere utilizzata in sicurezza in protocolli crittografici la cui analisi di sicurezza assume un random oracle che emette punti uniformemente casuali su una curva ellittica. Come discutono Ristenpart et al. in [RSS11], tuttavia, non tutte le dimostrazioni di sicurezza che fanno affidamento su random oracle continuano a valere quando tali oracle sono sostituiti da funzionalità indifferenziabili. Questa limitazione dovrebbe essere considerata quando si analizza la sicurezza dei protocolli che fanno affidamento sulla funzione hash_to_curve.
10.2. Hashing di password
Quando si esegue l'hash di password utilizzando una qualsiasi funzione descritta in questo documento, un avversario che apprende l'output della funzione di hash (o potenzialmente qualsiasi valore intermedio, ad esempio l'output di hash_to_field) potrebbe essere in grado di condurre un attacco a dizionario. Per mitigare tali attacchi, si raccomanda di eseguire prima una funzione di derivazione di chiave più costosa (es. PBKDF2 [RFC8018], scrypt [RFC7914] o Argon2 [RFC9106]) sulla password, quindi eseguire l'hash dell'output di tale funzione verso la curva ellittica target. Per la resistenza alle collisioni, la funzione di hash alla base della funzione di derivazione di chiave dovrebbe essere scelta secondo le linee guida elencate nella Sezione 5.3.1.
10.3. Requisiti in tempo costante
Le implementazioni in tempo costante di tutte le funzioni di questo documento sono FORTEMENTE RACCOMANDATE per tutti gli usi, per evitare la perdita di informazioni tramite canali laterali. È particolarmente importante utilizzare un'implementazione in tempo costante quando gli input a una codifica sono valori segreti; in tali casi, le implementazioni in tempo costante sono RICHIESTE per la sicurezza contro attacchi temporali (es. [VR20]). Quando sono richieste implementazioni in tempo costante, tutte le operazioni di base e le funzioni di utilità devono essere implementate in tempo costante, come discusso nella Sezione 4. In alcune applicazioni (es. sistemi embedded), la perdita attraverso altri canali laterali (es. canali laterali di potenza o elettromagnetici) può essere rilevante. Difendersi da tale perdita è al di fuori dello scopo di questo documento, poiché la natura della perdita e la difesa appropriata dipendono dall'applicazione.
10.4. encode_to_curve: distribuzione di output e indifferenziabilità
La funzione encode_to_curve (Sezione 3) restituisce punti campionati da una distribuzione statisticamente lontana dall'uniforme. Questa distribuzione è limitata approssimativamente come segue: in primo luogo, include almeno un ottavo dei punti in G, e in secondo luogo, la probabilità dei punti nella distribuzione varia al massimo di un fattore quattro. Questi limiti valgono quando encode_to_curve è istanziata con una qualsiasi delle funzioni map_to_curve della Sezione 6.
I limiti sopra sono derivati da diversi lavori in letteratura. Nello specifico:
-
Shallue e van de Woestijne [SW06] e Fouque e Tibouchi [FT12] derivano limiti per il mapping Shallue-van de Woestijne (Sezione 6.6.1).
-
Fouque e Tibouchi [FT10] e Tibouchi [T14] derivano limiti per il mapping Simplified SWU (Sezioni 6.6.2 e 6.6.3).
-
Bernstein et al. [BHKL13] derivano limiti per il mapping Elligator 2 (Sezioni 6.7.1 e 6.8.2).
L'indifferenziabilità di encode_to_course segue da un argomento simile a quello dato da Brier et al. [BCIMRT10]; lo abbozziamo brevemente come segue. Si consideri un random oracle ideale Hc() che campiona dalla distribuzione indotta dalla funzione map_to_curve chiamata da encode_to_curve, e si assuma per semplicità che la curva ellittica target abbia cofattore 1 (un argomento simile si applica per cofattori diversi da 1). L'indifferenziabilità vale se è possibile simulare in modo efficiente il random oracle "interno" in encode_to_curve, cioè hash_to_field. Il simulatore funziona così: su una query nuova msg, il simulatore interroga Hc(msg) e riceve un punto P nell'immagine di map_to_curve (se msg è uguale a una query precedente, il simulatore restituisce semplicemente il valore dato in risposta a quella query). Il simulatore calcola quindi i possibili preimmagini di P sotto map_to_curve, cioè gli elementi u di F tali che map_to_curve(u) == P (Tibouchi [T14] mostra che ciò può essere fatto in modo efficiente per le mappe Shallue-van de Woestijne e Simplified SWU, e Bernstein et al. mostrano lo stesso per Elligator 2). Il simulatore ne seleziona uno a caso e restituisce questo valore come output simulato del random oracle "interno". Per ipotesi, Hc() campiona dalla distribuzione indotta da map_to_curve su un elemento di input uniformemente casuale di F, quindi questo valore è uniformemente casuale e induce il punto corretto P quando passato attraverso map_to_curve.
10.5. Sicurezza di hash_to_field
La funzione hash_to_field, definita nella Sezione 5, è indifferenziabile da un random oracle [MRH04] quando expand_message (Sezione 5.3) è modellata come un random oracle. Poiché le dimostrazioni di indifferenziabilità sono componibili, ciò vale anche quando expand_message è dimostrata indifferenziabile da un random oracle rispetto a una primitiva sottostante modellata come un random oracle. Seguendo le linee guida della Sezione 5.3, entrambe le varianti di expand_message definite in quella sezione soddisfano questo requisito (si veda anche la Sezione 10.6).
Abbozziamo molto brevemente l'argomento di indifferenziabilità per hash_to_field. Si noti che ciascun intero modulo p che hash_to_field restituisce (cioè, ciascun elemento della rappresentazione vettoriale di F) è un membro di una classe di equivalenza di circa 2^k interi di lunghezza log2(p) + k bit, tutti uguali modulo p. Per ciascun intero modulo p che hash_to_field restituisce, il simulatore ne campiona uno a caso dalla classe di equivalenza e ne emette la stringa di byte restituita da I2OSP. (Si noti che questa è essenzialmente l'inversa della procedura hash_to_field.)
10.6. Sicurezza di expand_message_xmd
La funzione expand_message_xmd, definita nella Sezione 5.3.1, è indifferenziabile da un random oracle [MRH04] quando vale una delle seguenti:
-
H è indifferenziabile da un random oracle,
-
H è una funzione di hash basata su spugna la cui funzione interna è modellata come una trasformazione casuale o permutazione casuale [BDPV08], oppure
-
H è una funzione di hash Merkle-Damgård la cui funzione di compressione è modellata come un random oracle [CDMP05].
Per i casi (1) e (2), l'indifferenziabilità di expand_message_xmd segue direttamente dall'indifferenziabilità di H.
Per il caso (3), cioè quando H è una funzione di hash Merkle-Damgård, l'indifferenziabilità segue dal Teorema 5 di [CDMP05]. In particolare, expand_message_xmd calcola b_0 prefissando il messaggio con un blocco di zeri più informazioni ausiliarie (lunghezza, contatore e DST). Quindi, ciascun blocco di output b_i, i >= 1 in expand_message_xmd è il risultato dell'invocazione di H su una codifica univoca e priva di prefissi di b_0. Ciò è vero, in primo luogo, perché la lunghezza dell'input a tutte tali invocazioni è uguale e fissata dalla scelta di H e DST, e in secondo luogo perché ciascun tale input ha un suffisso univoco (a causa dell'inclusione del byte contatore I2OSP(i, 1)).
La differenza essenziale tra la costruzione discussa in [CDMP05] e expand_message_xmd è che quest'ultima esegue l'hash di un contatore accodato a strxor(b_0, b_(i - 1)) (Sezione 5.3.1, passo 10) invece che a b_0. Questo approccio aumenta la distanza di Hamming tra gli input a diverse invocazioni di H, il che riduce la probabilità che non idealità in H influenzino la distribuzione dei valori b_i.
Si noti che expand_message_xmd può essere utilizzata per istanziare una funzionalità indifferenziabile di uso generale con output a lunghezza variabile basata su qualsiasi funzione di hash che soddisfi uno dei criteri sopra. Le applicazioni che utilizzano expand_message_xmd al di fuori di hash_to_field dovrebbero garantire la separazione dei domini scegliendo un valore distinto per DST.
10.7. Separazione dei domini per le varianti di expand_message
Come discusso nella Sezione 2.2.5, lo scopo della separazione dei domini è garantire che le analisi di sicurezza di protocolli crittografici che interrogano più random oracle indipendenti rimangano valide anche se tutti questi random oracle sono istanziati sulla base di una singola funzione sottostante H.
Le varianti expand_message in questo documento (Sezione 5.3) garantiscono la separazione dei domini accodando un tag di separazione dei domini DST_prime, codificato privo di suffissi, a tutte le stringhe sottoposte a hash da H, una funzione di hash o a output estendibile sottostante. (Ci si aspetta che anche altre varianti expand_message che seguono le linee guida della Sezione 5.3.4 si comportino in modo simile, ma esse dovrebbero essere analizzate caso per caso.) Per la sicurezza, le applicazioni che utilizzano la stessa funzione H al di fuori di expand_message dovrebbero imporre la separazione dei domini tra tali usi di H e expand_message, e dovrebbero separare tutti questi dagli usi di H in altre applicazioni.
Questa sezione suggerisce quattro metodi per imporre la separazione dei domini dalle varianti expand_message, spiega come ciascun metodo ottiene la separazione dei domini e ne elenca le situazioni di impiego appropriate. Questi metodi condividono una struttura di alto livello: il progettista dell'applicazione fissa un tag DST_ext distinto da DST_prime e aumenta le chiamate a H con DST_ext. Ciascun metodo aumenta le chiamate a H in modo diverso e ciascuno può imporre requisiti aggiuntivi su DST_ext.
Questi metodi possono essere utilizzati per istanziare più funzioni separate per dominio (es. H1 e H2) selezionando valori DST_ext distinti per ciascuna (es. DST_ext1, DST_ext2).
-
(Separazione dei domini solo suffisso.) Questo metodo è utile per separare per dominio le invocazioni di H da expand_message_xmd o expand_message_xof. Non è appropriato per separare per dominio expand_message da HMAC-H [RFC2104]; a tale scopo, si veda il metodo 4.
Per istanziare una funzione separata per dominio solo suffisso Hso, calcolare
Hso(msg) = H(msg || DST_ext)DST_ext dovrebbe essere codificato privo di suffissi (es. accodando un byte che codifica la lunghezza di DST_ext) per rendere impossibile trovare coppie distinte (msg, DST_ext) che diano lo stesso valore di hash.
Questo metodo garantisce la separazione dei domini perché tutte le invocazioni distinte di H hanno suffissi distinti, poiché DST_ext è distinto da DST_prime.
-
(Separazione dei domini prefisso-suffisso.) Questo metodo può essere utilizzato negli stessi casi del metodo solo suffisso.
Per istanziare una funzione separata per dominio prefisso-suffisso Hps, calcolare
Hps(msg) = H(DST_ext || msg || I2OSP(0, 1))DST_ext dovrebbe essere codificato privo di prefissi (es. aggiungendo un prefisso di un byte che codifica la lunghezza di DST_ext) per rendere impossibile trovare coppie distinte (msg, DST_ext) che diano lo stesso valore di hash.
Questo metodo garantisce la separazione dei domini perché accodare il byte I2OSP(0, 1) assicura che gli input a H dentro Hps siano distinti da quelli dentro expand_message. Nello specifico, l'ultimo byte di DST_prime codifica la lunghezza di DST, che è richiesto essere non nulla (Sezione 3.1, requisito 2), e DST_prime è sempre accodata alle invocazioni di H dentro expand_message.
-
(Separazione dei domini solo prefisso.) Questo metodo è utile solo per separare per dominio le invocazioni di H da expand_message_xmd. Non dà separazione dei domini per expand_message_xof né per HMAC-H.
Per istanziare una funzione separata per dominio solo prefisso Hpo, calcolare
Hpo(msg) = H(DST_ext || msg)Affinché questo metodo dia separazione dei domini, DST_ext dovrebbe essere lungo almeno b bit, dove b è il numero di bit emessi dalla funzione di hash H. Inoltre, almeno uno dei primi b bit deve essere non nullo. Infine, DST_ext dovrebbe essere codificato privo di prefissi (es. aggiungendo un prefisso di un byte che codifica la lunghezza di DST_ext) per rendere impossibile trovare coppie distinte (msg, DST_ext) che diano lo stesso valore di hash.
Questo metodo garantisce la separazione dei domini nei seguenti modi. In primo luogo, poiché DST_ext contiene almeno un bit non nullo tra i suoi primi b bit, è garantito essere distinto dal valore Z_pad (Sezione 5.3.1, passo 4), il che assicura che tutti gli input a H siano distinti dall'input usato per generare b_0 in expand_message_xmd. In secondo luogo, poiché DST_ext è lungo almeno b bit, è quasi certamente distinto dai valori b_0 e strxor(b_0, b_(i - 1)), e pertanto tutti gli input a H sono distinti dagli input usati per generare b_i, i >= 1, con alta probabilità.
-
(Separazione dei domini XMD-HMAC.) Questo metodo è utile per separare per dominio le invocazioni di H dentro HMAC-H (cioè, HMAC [RFC2104] istanziata con la funzione di hash H) da expand_message_xmd. Si applica anche a HKDF-H (cioè, HKDF [RFC5869] istanziata con la funzione di hash H), come discusso di seguito.
Nello specifico, questo metodo si applica quando HMAC-H è utilizzata con una chiave non segreta per istanziare un random oracle basato su una funzione di hash H (si noti che expand_message_xmd può essere utilizzata anche a questo scopo; si veda la Sezione 10.6). Quando si utilizza HMAC-H con una chiave segreta ad alta entropia, la separazione dei domini non è necessaria; si veda la discussione di seguito.
Per scegliere una chiave HMAC non segreta DST_key che garantisca la separazione dei domini da expand_message_xmd, calcolare
DST_key_preimage = "DERIVE-HMAC-KEY-" || DST_ext || I2OSP(0, 1)
DST_key = H(DST_key_preimage)Quindi, per istanziare il random oracle Hro utilizzando HMAC-H, calcolare
Hro(msg) = HMAC-H(DST_key, msg)Lo zero finale in DST_key_preimage assicura che questo valore sia distinto dagli input a H dentro expand_message_xmd (perché tutti tali input hanno suffisso DST_prime, che non può terminare con un byte zero come discusso sopra). Ciò garantisce la separazione dei domini perché, con probabilità schiacciante, tutti gli input a H dentro HMAC-H usando la chiave DST_key hanno prefissi distinti dai valori Z_pad, b_0 e strxor(b_0, b_(i - 1)) dentro expand_message_xmd.
Per gli usi di HMAC-H che istanziano un random oracle privato fissando una chiave segreta ad alta entropia, la separazione dei domini da expand_message_xmd non è necessaria. Ciò è dovuto al fatto che, in modo simile al caso sopra, tutti gli input a H dentro HMAC-H usando questa chiave segreta hanno quasi certamente prefissi distinti da tutti gli input a H dentro expand_message_xmd.
Infine, questo metodo può essere utilizzato con HKDF-H [RFC5869] fissando l'input salt di HKDF-Extract a DST_key, calcolato come sopra. Ciò garantisce la separazione dei domini per HKDF-Extract per lo stesso argomento di HMAC-H che usa DST_key. Inoltre, supponendo che il materiale di chiave di input (IKM) fornito a HKDF-Extract abbia entropia sufficientemente alta (diciamo, commisurata al parametro di sicurezza), lo step HKDF-Expand è separato per dominio per lo stesso argomento di HMAC-H con una chiave segreta ad alta entropia (poiché una chiave pseudo-casuale è esattamente ciò).
10.8. Livelli di sicurezza target
Ciascuna ciphersuite specifica un livello di sicurezza target (in bit) per la curva sottostante. Questo parametro garantisce che l'istanziazione corrispondente di hash_to_field sia conservativa e corretta. Sottolineiamo che questo parametro è solo un limite superiore al livello di sicurezza della curva e non è né una garanzia né un avallo della sua idoneità per una data applicazione. Progressi matematici e crittografici possono ridurre il livello di sicurezza effettivo per qualsiasi curva.