Passa al contenuto principale

7. Schemi di cifratura (Encryption Schemes)

Ai fini di questo documento, uno schema di cifratura (Encryption Scheme) è composto da un'operazione di cifratura e un'operazione di decifratura, dove l'operazione di cifratura genera un testo cifrato da un messaggio utilizzando la chiave pubblica RSA del destinatario, e l'operazione di decifratura recupera un messaggio da un testo cifrato utilizzando la corrispondente chiave privata RSA del destinatario.

Gli schemi di cifratura possono essere applicati a una varietà di scenari applicativi. Un'applicazione tipica è il protocollo di stabilimento di chiave (Key Establishment Protocol), dove il messaggio contiene materiale chiave che deve essere trasferito in modo confidenziale da una parte a un'altra. Ad esempio, PKCS #7 [RFC2315] utilizza tali protocolli per trasferire una chiave di cifratura del contenuto da un mittente a un destinatario; gli schemi di cifratura definiti in questo documento sono adatti per essere utilizzati come algoritmi di cifratura delle chiavi in tale contesto.

Questo documento specifica due schemi di cifratura: RSAES-OAEP e RSAES-PKCS1-v1_5. Le nuove applicazioni DEVONO (REQUIRED) supportare RSAES-OAEP; RSAES-PKCS1-v1_5 è incluso solo per la compatibilità con le applicazioni esistenti.

Gli schemi di cifratura presentati qui seguono un modello generale simile a quello utilizzato in IEEE 1363 [IEEE1363], combinando primitive di cifratura e decifratura con un metodo di codifica per la cifratura. L'operazione di cifratura applica un'operazione di codifica del messaggio al messaggio per produrre un messaggio codificato, che viene poi convertito in un rappresentante del messaggio intero. La primitiva di cifratura viene applicata al rappresentante del messaggio per produrre il testo cifrato. Viceversa, l'operazione di decifratura applica la primitiva di decifratura al testo cifrato per recuperare il rappresentante del messaggio, che viene poi convertito in una stringa di ottetti del messaggio codificato. Un'operazione di decodifica del messaggio viene applicata al messaggio codificato per recuperare il messaggio e verificare la correttezza della decifratura.

Per evitare debolezze di implementazione legate al modo in cui gli errori vengono gestiti nell'operazione di decodifica (vedere [BLEICHENBACHER] e [MANGER]), le operazioni di codifica e decodifica di RSAES-OAEP e RSAES-PKCS1-v1_5 sono incorporate nelle specifiche dei rispettivi schemi di cifratura, anziché essere definite in specifiche separate. Entrambi gli schemi di cifratura sono compatibili con i corrispondenti schemi in PKCS #1 v2.1.

7.1. RSAES-OAEP

RSAES-OAEP combina le primitive RSAEP e RSADP (Sezione 5.1) con il metodo di codifica EME-OAEP (incorporato in questa sezione). Si basa sul metodo di padding ottimale per la cifratura asimmetrica (Optimal Asymmetric Encryption Padding, OAEP) di Bellare e Rogaway, introdotto per la prima volta in [OAEP]. EME-OAEP è una variante unidirezionale di EME-OAEP in IEEE 1363 [IEEE1363].

Lo schema non è deterministico: per una data chiave pubblica e un dato messaggio, possono essere generati molti testi cifrati possibili.

RSAES-OAEP è raccomandato per le nuove applicazioni. RSAES-OAEP può essere utilizzato come alternativa preferibile a RSAES-PKCS1-v1_5 in qualsiasi applicazione.

La sicurezza di questo schema si basa sulla difficoltà di due funzioni: il problema RSA e il modello oracle casuale della funzione di generazione maschera (Mask Generation Function, MGF). Le proprietà di sicurezza di queste due funzioni sono incarnate in una prova di teorema che mostra che la difficoltà di utilizzare RSAES-OAEP contro un attacco con testo cifrato scelto (Chosen Ciphertext Attack) è essenzialmente difficile quanto risolvere il problema RSA, a condizione che il MGF si comporti come un oracle casuale (Random Oracle).

7.1.1. Operazione di cifratura (Encryption Operation)

RSAES-OAEP-ENCRYPT ((n, e), M, L)

Input (Input):

  • (n, e): chiave pubblica RSA del destinatario (k denota la lunghezza in ottetti del modulo)
  • M: messaggio da cifrare, una stringa di ottetti di lunghezza al massimo k - 2hLen - 2, dove hLen è la lunghezza di output in ottetti della funzione hash Hash
  • L: etichetta opzionale (Label) associata all'operazione di cifratura; il valore predefinito è la stringa vuota

Output (Output):

  • C: testo cifrato, una stringa di ottetti di lunghezza k

Errori (Errors):

  • "message too long" (messaggio troppo lungo)
  • "label too long" (etichetta troppo lunga)

Assunzione (Assumption): La chiave pubblica RSA (n, e) è valida

Passi (Steps):

  1. Controllo di lunghezza: Se la lunghezza di L è superiore al limite di input per la funzione di generazione maschera (che è 2^61 - 1 ottetti), restituire "label too long" e fermarsi.

  2. Codifica EME-OAEP:

    • Se la lunghezza di M è superiore a k - 2hLen - 2 ottetti, restituire "message too long" e fermarsi.
    • Sia lHash = Hash(L), una stringa di ottetti di lunghezza hLen.
    • Generare una stringa di padding PS costituita da k - mLen - 2hLen - 2 ottetti zero e un singolo ottetto di valore 0x01.
    • Concatenare lHash, PS, il singolo byte 0x01 e il messaggio M per formare il blocco dati DB: DB = lHash || PS || 0x01 || M
    • Generare una stringa di ottetti casuale seed di lunghezza hLen.
    • Sia dbMask = MGF(seed, k - hLen - 1).
    • Sia maskedDB = DB ⊕ dbMask.
    • Sia seedMask = MGF(maskedDB, hLen).
    • Sia maskedSeed = seed ⊕ seedMask.
    • Concatenare un singolo ottetto di valore 0x00, maskedSeed e maskedDB per formare il messaggio codificato EM: EM = 0x00 || maskedSeed || maskedDB
  3. Cifratura RSA:

    • Convertire il messaggio codificato EM in un rappresentante del messaggio intero m: m = OS2IP(EM)
    • Applicare la primitiva di cifratura RSAEP: c = RSAEP((n, e), m)
    • Convertire il rappresentante del testo cifrato c in un testo cifrato C di lunghezza k: C = I2OSP(c, k)
  4. Restituire il testo cifrato C.

7.1.2. Operazione di decifratura (Decryption Operation)

RSAES-OAEP-DECRYPT (K, C, L)

Input (Input):

  • K: chiave privata RSA del destinatario
  • C: testo cifrato da decifrare, una stringa di ottetti di lunghezza k, dove k è la lunghezza in ottetti del modulo RSA n
  • L: etichetta opzionale il cui valore è associato all'etichetta durante l'operazione di cifratura che ha generato il testo cifrato; il valore predefinito è la stringa vuota

Output (Output):

  • M: messaggio, una stringa di ottetti di lunghezza al massimo k - 2hLen - 2

Errore (Error):

  • "decryption error" (errore di decifratura)

Passi (Steps):

  1. Controllo di lunghezza: Se la lunghezza di L è superiore al limite di input, restituire "decryption error" e fermarsi. Se la lunghezza del testo cifrato C non è di k ottetti (o se k < 2hLen + 2), restituire "decryption error" e fermarsi.

  2. Decifratura RSA:

    • Convertire il testo cifrato C in un rappresentante del testo cifrato intero c: c = OS2IP(C)
    • Applicare la primitiva di decifratura RSADP: m = RSADP(K, c). Se RSADP restituisce "ciphertext representative out of range", restituire "decryption error" e fermarsi.
    • Convertire il rappresentante del messaggio m in un messaggio codificato EM di lunghezza k: EM = I2OSP(m, k)
  3. Decodifica EME-OAEP:

    • Sia lHash = Hash(L).
    • Separare EM in un singolo ottetto Y, una stringa di ottetti maskedSeed di lunghezza hLen e una stringa di ottetti maskedDB di lunghezza k - hLen - 1: EM = Y || maskedSeed || maskedDB
    • Sia seedMask = MGF(maskedDB, hLen).
    • Sia seed = maskedSeed ⊕ seedMask.
    • Sia dbMask = MGF(seed, k - hLen - 1).
    • Sia DB = maskedDB ⊕ dbMask.
    • Separare DB in una stringa di ottetti lHash' di lunghezza hLen, una stringa di padding PS (possibilmente vuota) composta da ottetti di valore 0x00, un singolo ottetto di valore 0x01 e un messaggio M: DB = lHash' || PS || 0x01 || M. Se non c'è un ottetto di valore 0x01 per separare PS e M, se lHash non è uguale a lHash', o se Y è diverso da zero, restituire "decryption error" e fermarsi.
  4. Restituire il messaggio M.

Nota: L'implementazione deve essere eseguita con attenzione per evitare che l'implementazione fornisca inavvertitamente informazioni utili a un avversario. In particolare, i messaggi di errore non devono rivelare se un ottetto in EM o altri ottetti in DB non sono della forma prevista.

7.2. RSAES-PKCS1-v1_5

RSAES-PKCS1-v1_5 combina le primitive RSAEP e RSADP (Sezione 5.1) con il metodo di codifica EME-PKCS1-v1_5. È incluso solo per la compatibilità con le applicazioni esistenti; per le nuove applicazioni, si raccomanda l'uso di RSAES-OAEP.

La sicurezza di RSAES-PKCS1-v1_5 dipende dalla difficoltà del problema RSA. Esistono debolezze potenziali note (vedere [BLEICHENBACHER]), quindi le nuove applicazioni dovrebbero utilizzare RSAES-OAEP.

7.2.1. Operazione di cifratura (Encryption Operation)

RSAES-PKCS1-V1_5-ENCRYPT ((n, e), M)

Gli input, output e passi sono simili a RSAES-OAEP, ma utilizzano la codifica EME-PKCS1-v1_5

7.2.2. Operazione di decifratura (Decryption Operation)

RSAES-PKCS1-V1_5-DECRYPT (K, C)

Gli input, output e passi sono simili a RSAES-OAEP, ma utilizzano la decodifica EME-PKCS1-v1_5

Nota di sicurezza importante: I messaggi di errore di decifratura non devono distinguere tra diversi tipi di errori per prevenire l'attacco con testo cifrato scelto di Bleichenbacher.