RFC 8017 - PKCS #1: Specifiche di crittografia RSA versione 2.2
- Stato: Informational
- Pubblicato: November 2016
- Stream: IETF
- Sostituisce: RFC3447
- Errata: Nessun errata
Riepilogo (Abstract)
Questo documento fornisce raccomandazioni per l'implementazione della crittografia a chiave pubblica basata sull'algoritmo RSA, coprendo primitive crittografiche, schemi di cifratura, schemi di firma con appendice e sintassi ASN.1 per rappresentare le chiavi e identificare gli schemi.
Questo documento rappresenta una ripubblicazione di PKCS #1 v2.2 della serie Public-Key Cryptography Standards (PKCS) di RSA Laboratories. Con la pubblicazione di questo RFC, il controllo delle modifiche viene trasferito all'IETF.
Questo documento rende anche obsoleto RFC 3447.
Stato di questo memo
Questo documento non è una specifica del percorso degli standard Internet; è pubblicato a scopi informativi.
Questo documento è un prodotto dell'Internet Engineering Task Force (IETF). Rappresenta il consenso della comunità IETF. Ha ricevuto una revisione pubblica ed è stato approvato per la pubblicazione dall'Internet Engineering Steering Group (IESG). Non tutti i documenti approvati dall'IESG sono candidati per qualsiasi livello di standard Internet; vedere Sezione 2 di RFC 7841.
Informazioni sullo stato attuale di questo documento, eventuali errata e come fornire feedback possono essere ottenute su http://www.rfc-editor.org/info/rfc8017.
Indice dei contenuti
- 1. Introduzione
- 1.1 Linguaggio dei requisiti
- 2. Notazione
- 3. Tipi di chiave
- 3.1 Chiave pubblica RSA
- 3.2 Chiave privata RSA
- 4. Primitive di conversione dati
- 4.1 I2OSP
- 4.2 OS2IP
- 5. Primitive crittografiche
- 5.1 Primitive di cifratura e decifratura
- 5.2 Primitive di firma e verifica
- 6. Panoramica degli schemi
- 7. Schemi di cifratura
- 7.1 RSAES-OAEP
- 7.2 RSAES-PKCS1-v1_5
- 8. Schema di firma con appendice
- 8.1 RSASSA-PSS
- 8.2 RSASSA-PKCS1-v1_5
- 9. Metodi di codifica per firme con appendice
- 9.1 EMSA-PSS
- 9.2 EMSA-PKCS1-v1_5
- 10. Considerazioni sulla sicurezza
- 11. Riferimenti
- 11.1 Riferimenti normativi
- 11.2 Riferimenti informativi
Appendici
- Appendice A. Sintassi ASN.1
- A.1 Rappresentazione della chiave RSA
- A.2 Identificazione dello schema
- Appendice B. Tecniche di supporto
- B.1 Funzioni hash
- B.2 Funzioni di generazione maschera
- Appendice C. Modulo ASN.1
- Appendice D. Cronologia delle revisioni di PKCS #1
- Appendice E. Informazioni su PKCS
Risorse correlate
- Testo ufficiale: RFC 8017
- Pagina ufficiale: RFC 8017 DataTracker
- Errata: RFC Editor Errata
- Documento reso obsoleto: RFC 3447 (PKCS #1 v2.1)
1. Introduzione (Introduction)
Questo documento fornisce raccomandazioni per l'implementazione della crittografia a chiave pubblica (Public-Key Cryptography) basata sull'algoritmo RSA [RSA], coprendo i seguenti aspetti:
- Primitive crittografiche (Cryptographic Primitives)
- Schemi di cifratura (Encryption Schemes)
- Schemi di firma con appendice (Signature Schemes with Appendix)
- Sintassi ASN.1 per rappresentare le chiavi e identificare gli schemi
Queste raccomandazioni sono destinate all'applicazione generale nei sistemi informatici e di comunicazione e includono quindi una notevole flessibilità. È previsto che gli standard applicativi basati su queste specifiche possano includere vincoli aggiuntivi. Queste raccomandazioni sono destinate a essere compatibili con gli standard IEEE 1363 [IEEE1363], IEEE 1363a [IEEE1363A] e ANSI X9.44 [ANSIX944].
Questo documento sostituisce PKCS #1 versione 2.1 [RFC3447] ma include tecniche compatibili.
L'organizzazione di questo documento è la seguente:
-
La sezione 1 è un'introduzione.
-
La sezione 2 definisce alcune notazioni utilizzate in questo documento.
-
La sezione 3 definisce i tipi di chiave pubblica e privata RSA.
-
Le sezioni 4 e 5 definiscono diverse primitive, o operazioni matematiche di base. Le primitive di conversione dati sono nella sezione 4, e le primitive crittografiche (cifratura-decifratura e firma-verifica) sono nella sezione 5.
-
Le sezioni 6, 7 e 8 trattano gli schemi di cifratura e firma in questo documento. La sezione 6 fornisce una panoramica. Oltre ai metodi trovati in PKCS #1 v1.5, la sezione 7 definisce uno schema di cifratura basato su Optimal Asymmetric Encryption Padding (OAEP) [OAEP], e la sezione 8 definisce uno schema di firma con appendice basato sul Probabilistic Signature Scheme (PSS) [RSARABIN] [PSS].
-
La sezione 9 definisce i metodi di codifica per gli schemi di firma nella sezione 8.
-
L'appendice A definisce la sintassi ASN.1 per le chiavi definite nella sezione 3 e gli schemi nelle sezioni 7 e 8.
-
L'appendice B definisce le funzioni hash (Hash Functions) e la funzione di generazione maschera (Mask Generation Function, MGF) utilizzate in questo documento, inclusa la sintassi ASN.1 per queste tecniche.
-
L'appendice C fornisce un modulo ASN.1.
-
Le appendici D ed E delineano la cronologia delle revisioni di PKCS #1 e forniscono informazioni generali sugli standard di crittografia a chiave pubblica (Public-Key Cryptography Standards).
Questo documento rappresenta una ripubblicazione di PKCS #1 v2.2 [PKCS1_22] dalla serie Public-Key Cryptography Standards (PKCS) di RSA Laboratories.
1.1. Linguaggio dei requisiti (Requirements Language)
Le parole chiave «MUST» (deve), «MUST NOT» (non deve), «REQUIRED» (richiesto), «SHALL» (deve), «SHALL NOT» (non deve), «SHOULD» (dovrebbe), «SHOULD NOT» (non dovrebbe), «RECOMMENDED» (raccomandato), «MAY» (può) e «OPTIONAL» (opzionale) in questo documento devono essere interpretate come descritto in [RFC2119].
2. Notazione (Notation)
La notazione in questo documento include:
| Simbolo | Descrizione |
|---|---|
| c | rappresentante del testo cifrato (Ciphertext Representative), un intero compreso tra 0 e n-1 |
| C | testo cifrato (Ciphertext), una stringa di ottetti (Octet String) |
| d | esponente privato RSA (RSA Private Exponent) |
| d_i | esponente CRT del fattore aggiuntivo r_i (Additional Factor r_i's CRT Exponent), un intero positivo tale che e * d_i == 1 (mod (r_i-1)), i = 3, ..., u |
| dP | esponente CRT di p, un intero positivo tale che e * dP == 1 (mod (p-1)) |
| dQ | esponente CRT di q, un intero positivo tale che e * dQ == 1 (mod (q-1)) |
| e | esponente pubblico RSA (RSA Public Exponent) |
| EM | messaggio codificato (Encoded Message), una stringa di ottetti |
| emBits | lunghezza (prevista) in bit di un messaggio codificato EM |
| emLen | lunghezza (prevista) in ottetti di un messaggio codificato EM |
| GCD(. , .) | massimo comun divisore di due interi non negativi (Greatest Common Divisor) |
| Hash | funzione hash (Hash Function) |
| hLen | lunghezza di output in ottetti della funzione hash Hash |
| k | lunghezza in ottetti del modulo RSA n |
| K | chiave privata RSA (RSA Private Key) |
| L | etichetta RSAES-OAEP opzionale (Label), una stringa di ottetti |
| LCM(., ..., .) | minimo comune multiplo di un elenco di interi non negativi (Least Common Multiple) |
| m | rappresentante del messaggio (Message Representative), un intero compreso tra 0 e n-1 |
| M | messaggio (Message), una stringa di ottetti |
| mask | output MGF, una stringa di ottetti |
| maskLen | lunghezza (prevista) della stringa di ottetti mask |
| MGF | funzione di generazione maschera (Mask Generation Function) |
| mgfSeed | seme da cui viene generata la maschera (Seed), una stringa di ottetti |
| mLen | lunghezza in ottetti di un messaggio M |
| n | modulo RSA (RSA Modulus), n = r_1 * r_2 * ... * r_u, u >= 2 |
| (n, e) | chiave pubblica RSA (RSA Public Key) |
| p, q | primi due fattori primi del modulo RSA n (Prime Factors) |
| qInv | coefficiente CRT (CRT Coefficient), un intero positivo minore di p tale che q * qInv == 1 (mod p) |
| r_i | fattori primi del modulo RSA n, inclusi r_1 = p, r_2 = q e fattori aggiuntivi se presenti |
| s | rappresentante della firma (Signature Representative), un intero compreso tra 0 e n-1 |
| S | firma (Signature), una stringa di ottetti |
| sLen | lunghezza in ottetti del sale EMSA-PSS (Salt) |
| t_i | coefficiente CRT del fattore primo aggiuntivo r_i, un intero positivo minore di r_i tale che r_1 * r_2 * ... * r_(i-1) * t_i == 1 (mod r_i), i = 3, ..., u |
| u | numero di fattori primi del modulo RSA, u >= 2 |
| x | un intero non negativo |
| X | una stringa di ottetti corrispondente a x |
| xLen | lunghezza (prevista) della stringa di ottetti X |
| 0x | indicatore di rappresentazione esadecimale di un ottetto o di una stringa di ottetti: «0x48» denota l'ottetto con valore esadecimale 48; «(0x)48 09 0e» denota la stringa di tre ottetti consecutivi con valori esadecimali 48, 09 e 0e, rispettivamente |
| λ(n) | LCM(r_1-1, r_2-1, ..., r_u-1) |
| ⊕ | OR esclusivo bit a bit di due stringhe di ottetti (Bit-wise Exclusive-OR) |
| ⌈.⌉ | funzione soffitto (Ceiling Function); ⌈x⌉ è il più piccolo intero maggiore o uguale al numero reale x |
| || | operatore di concatenazione (Concatenation Operator) |
| == | simbolo di congruenza (Congruence Symbol); a == b (mod n) significa che l'intero n divide l'intero a - b |
Nota: Il teorema del resto cinese (Chinese Remainder Theorem, CRT) può essere applicato in modo non ricorsivo e ricorsivo. In questo documento, viene utilizzato un approccio ricorsivo seguendo l'algoritmo di Garner [GARNER]. Vedere anche la nota 1 nella sezione 3.2.
3. Tipi di chiave (Key Types)
Due tipi di chiave sono impiegati nelle primitive e negli schemi definiti in questo documento: chiave pubblica RSA (RSA Public Key) e chiave privata RSA (RSA Private Key). Insieme, una chiave pubblica RSA e una chiave privata RSA formano una coppia di chiavi RSA (RSA Key Pair).
Questa specifica supporta il cosiddetto RSA « multi-primo » (Multi-prime), dove il modulo può avere più di due fattori primi. Il vantaggio dell'RSA multi-primo è un costo computazionale inferiore per le primitive di decifratura e firma, a condizione che venga utilizzato il teorema del resto cinese (Chinese Remainder Theorem, CRT). Possono essere ottenute migliori prestazioni su piattaforme monoprocessore, ma in misura maggiore su piattaforme multiprocessore, dove le esponenziazioni modulari coinvolte possono essere eseguite in parallelo.
Per una discussione su come il multi-primo influenzi la sicurezza del crittosistema RSA, il lettore è rimandato a [SILVERMAN].
3.1. Chiave pubblica RSA (RSA Public Key)
Ai fini di questo documento, una chiave pubblica RSA è composta da due componenti:
n modulo RSA (RSA Modulus), un intero positivo
e esponente pubblico RSA (RSA Public Exponent), un intero positivo
In una chiave pubblica RSA valida, il modulo RSA n è un prodotto di u numeri primi dispari distinti r_i, i = 1, 2, ..., u, dove u >= 2, e l'esponente pubblico RSA e è un intero compreso tra 3 e n - 1 che soddisfa GCD(e, λ(n)) = 1, dove λ(n) = LCM(r_1 - 1, ..., r_u - 1). Per convenzione, i primi due numeri primi r_1 e r_2 possono anche essere denotati rispettivamente come p e q.
Una sintassi raccomandata per lo scambio di chiavi pubbliche RSA tra implementazioni è data nell'appendice A.1.1; la rappresentazione interna di un'implementazione può differire.
3.2. Chiave privata RSA (RSA Private Key)
Ai fini di questo documento, una chiave privata RSA può avere una di due rappresentazioni.
Rappresentazione 1
La prima rappresentazione consiste nella coppia (n, d), dove i componenti hanno i seguenti significati:
n modulo RSA (RSA Modulus), un intero positivo
d esponente privato RSA (RSA Private Exponent), un intero positivo
Rappresentazione 2
La seconda rappresentazione consiste in una quintupla (p, q, dP, dQ, qInv) e una sequenza (eventualmente vuota) di triple (r_i, d_i, t_i), i = 3, ..., u, una per ogni numero primo non presente nella quintupla, dove i componenti hanno i seguenti significati:
p il primo fattore, un intero positivo
q il secondo fattore, un intero positivo
dP esponente CRT del primo fattore, un intero positivo
dQ esponente CRT del secondo fattore, un intero positivo
qInv il (primo) coefficiente CRT, un intero positivo
r_i l'i-esimo fattore, un intero positivo
d_i esponente CRT dell'i-esimo fattore, un intero positivo
t_i coefficiente CRT dell'i-esimo fattore, un intero positivo
Vincoli di validità
In una chiave privata RSA valida con la prima rappresentazione, il modulo RSA n è lo stesso della chiave pubblica RSA corrispondente ed è il prodotto di u numeri primi dispari distinti r_i, i = 1, 2, ..., u, dove u >= 2. L'esponente privato RSA d è un intero positivo minore di n che soddisfa:
e * d == 1 (mod λ(n))
dove e è l'esponente pubblico RSA corrispondente e λ(n) è definito come nella sezione 3.1.
In una chiave privata RSA valida con la seconda rappresentazione, i due fattori p e q sono i primi due fattori primi del modulo RSA n (cioè, r_1 e r_2); gli esponenti CRT dP e dQ sono interi positivi minori di p e q, rispettivamente, che soddisfano:
e * dP == 1 (mod (p-1))
e * dQ == 1 (mod (q-1))
e il coefficiente CRT qInv è un intero positivo minore di p che soddisfa:
q * qInv == 1 (mod p)
Se u > 2, la rappresentazione includerà una o più triple (r_i, d_i, t_i), i = 3, ..., u. I fattori r_i sono i fattori primi aggiuntivi del modulo RSA n. Ogni esponente CRT d_i (i = 3, ..., u) soddisfa:
e * d_i == 1 (mod (r_i - 1))
Ogni coefficiente CRT t_i (i = 3, ..., u) è un intero positivo minore di r_i che soddisfa:
R_i * t_i == 1 (mod r_i)
dove R_i = r_1 * r_2 * ... * r_(i-1).
Una sintassi raccomandata per lo scambio di chiavi private RSA tra implementazioni, che include componenti di entrambe le rappresentazioni, è data nell'appendice A.1.2; la rappresentazione interna di un'implementazione può differire.
Note
Nota 1: La definizione dei coefficienti CRT qui e le formule che li utilizzano nelle primitive nella sezione 5 seguono generalmente l'algoritmo di Garner [GARNER] (vedere anche l'algoritmo 14.71 in [HANDBOOK]). Tuttavia, per compatibilità con le rappresentazioni delle chiavi private RSA in PKCS #1 v2.0 e versioni precedenti, i ruoli di p e q sono invertiti rispetto al resto dei numeri primi. Pertanto, il primo coefficiente CRT, qInv, è definito come l'inverso di q mod p, piuttosto che come l'inverso di R_1 mod r_2, cioè, di p mod q.
Nota 2: Quisquater e Couvreur [FASTDEC] hanno osservato il vantaggio di applicare il CRT alle operazioni RSA.
4. Primitive di conversione dati (Data Conversion Primitives)
Due primitive di conversione dati (Data Conversion Primitives) sono utilizzate negli schemi definiti in questo documento:
- I2OSP - Primitiva da intero a stringa di ottetti (Integer-to-Octet-String Primitive)
- OS2IP - Primitiva da stringa di ottetti a intero (Octet-String-to-Integer Primitive)
Ai fini di questo documento, e in coerenza con la sintassi ASN.1, una stringa di ottetti (Octet String) è una sequenza ordinata di ottetti (byte a 8 bit). Questa sequenza è indicizzata dal primo (per convenzione, il più a sinistra) all'ultimo (il più a destra). Per le conversioni con interi, nelle seguenti primitive di conversione, il primo ottetto è considerato il più significativo.
4.1. I2OSP
I2OSP converte un intero non negativo in una stringa di ottetti di lunghezza specificata.
I2OSP (x, xLen)
Input (Input)
x intero non negativo da convertire
xLen lunghezza prevista della stringa di ottetti risultante
Output (Output)
X stringa di ottetti corrispondente di lunghezza xLen
Errore (Error)
"integer too large" (intero troppo grande)
Passi (Steps)
Passo 1. Se x >= 256^xLen, restituire "integer too large" e fermarsi.
Passo 2. Scrivere l'intero x nella sua rappresentazione unica in base 256 a xLen cifre:
x = x_(xLen-1) * 256^(xLen-1) + x_(xLen-2) * 256^(xLen-2) + ... + x_1 * 256 + x_0
dove 0 <= x_i < 256 (si noti che se x è minore di 256^(xLen-1), una o più cifre iniziali saranno zero).
Passo 3. Sia il valore intero dell'ottetto X_i uguale a x_(xLen-i), dove 1 <= i <= xLen. Restituire la stringa di ottetti:
X = X_1 X_2 ... X_xLen
4.2. OS2IP
OS2IP converte una stringa di ottetti in un intero non negativo.
OS2IP (X)
Input (Input)
X stringa di ottetti da convertire
Output (Output)
x intero non negativo corrispondente
Passi (Steps)
Passo 1. Siano X_1 X_2 ... X_xLen gli ottetti di X dal primo all'ultimo, e sia x_(xLen-i) il valore intero dell'ottetto X_i, dove 1 <= i <= xLen.
Passo 2. Sia:
x = x_(xLen-1) * 256^(xLen-1) + x_(xLen-2) * 256^(xLen-2) + ... + x_1 * 256 + x_0
Passo 3. Restituire x.
5. Primitive crittografiche (Cryptographic Primitives)
Le primitive crittografiche (Cryptographic Primitives) sono operazioni matematiche di base da cui possono essere costruiti schemi crittografici. Sono destinate ad essere utilizzate in implementazioni hardware o come moduli software, e non sono destinate a fornire sicurezza indipendentemente dagli schemi.
Questo documento specifica quattro tipi di primitive, organizzate in coppie: cifratura e decifratura (Encryption and Decryption); firma e verifica (Signature and Verification).
La specifica delle primitive presuppone che gli input soddisfino determinate condizioni, in particolare che le chiavi pubbliche e private RSA siano valide.
5.1. Primitive di cifratura e decifratura (Encryption and Decryption Primitives)
Una primitiva di cifratura (Encryption Primitive) produce un rappresentante del testo cifrato da un rappresentante del messaggio sotto il controllo di una chiave pubblica, e una primitiva di decifratura (Decryption Primitive) recupera un rappresentante del messaggio da un rappresentante del testo cifrato sotto il controllo della chiave privata corrispondente.
Una coppia di primitive di cifratura e decifratura è utilizzata negli schemi di cifratura definiti in questo documento ed è specificata qui: primitiva di cifratura RSA (RSAEP, RSA Encryption Primitive) / primitiva di decifratura RSA (RSADP, RSA Decryption Primitive). RSAEP e RSADP coinvolgono la stessa operazione matematica, con chiavi diverse in input. Le primitive qui definite sono identiche alla primitiva di cifratura per fattorizzazione di interi usando RSA (IFEP-RSA) / primitiva di decifratura per fattorizzazione di interi usando RSA (IFDP-RSA) in IEEE 1363 [IEEE1363] (ad eccezione dell'aggiunta del supporto per RSA multi-primo), e sono compatibili con PKCS #1 v1.5.
L'operazione matematica principale in ogni primitiva è l'esponenziazione (Exponentiation).
5.1.1. RSAEP
RSAEP ((n, e), m)
Input (Input)
(n, e) chiave pubblica RSA
m rappresentante del messaggio, un intero compreso tra 0 e n - 1
Output (Output)
c rappresentante del testo cifrato, un intero compreso tra 0 e n - 1
Errore (Error)
"message representative out of range" (rappresentante del messaggio fuori intervallo)
Assunzione (Assumption)
La chiave pubblica RSA (n, e) è valida
Passi (Steps)
Passo 1. Se il rappresentante del messaggio m non è compreso tra 0 e n - 1, restituire "message representative out of range" e fermarsi.
Passo 2. Sia c = m^e mod n.
Passo 3. Restituire c.
5.1.2. RSADP
RSADP (K, c)
Input (Input)
K chiave privata RSA, dove K ha una delle seguenti forme:
- coppia (n, d)
- quintupla (p, q, dP, dQ, qInv) e sequenza possibilmente vuota di triple (r_i, d_i, t_i), i = 3, ..., u
c rappresentante del testo cifrato, un intero compreso tra 0 e n - 1
Output (Output)
m rappresentante del messaggio, un intero compreso tra 0 e n - 1
Errore (Error)
"ciphertext representative out of range" (rappresentante del testo cifrato fuori intervallo)
Assunzione (Assumption)
La chiave privata RSA K è valida
Passi (Steps)
Passo 1. Se il rappresentante del testo cifrato c non è compreso tra 0 e n - 1, restituire "ciphertext representative out of range" e fermarsi.
Passo 2. Il rappresentante del messaggio m è calcolato come segue:
a. Se viene utilizzata la prima forma di K (n, d), sia m = c^d mod n.
b. Se viene utilizzata la seconda forma di K (p, q, dP, dQ, qInv) e (r_i, d_i, t_i), procedere come segue:
i. Sia m_1 = c^dP mod p e m_2 = c^dQ mod q.
ii. Se u > 2, sia m_i = c^(d_i) mod r_i, i = 3, ..., u.
iii. Sia h = (m_1 - m_2) * qInv mod p.
iv. Sia m = m_2 + q * h.
v. Se u > 2, sia R = r_1 e per i = 3 a u, eseguire:
- Sia R = R * r_(i-1).
- Sia h = (m_i - m) * t_i mod r_i.
- Sia m = m + R * h.
Passo 3. Restituire m.
Nota: Il passo 2.b può essere riscritto come un singolo ciclo, a condizione che l'ordine di p e q sia invertito. Tuttavia, per coerenza con PKCS #1 v2.0, i primi due numeri primi p e q sono trattati separatamente dai numeri primi aggiuntivi.
5.2. Primitive di firma e verifica (Signature and Verification Primitives)
Una primitiva di firma (Signature Primitive) produce un rappresentante della firma da un rappresentante del messaggio sotto il controllo di una chiave privata, e una primitiva di verifica (Verification Primitive) recupera un rappresentante del messaggio da un rappresentante della firma sotto il controllo della chiave pubblica corrispondente. Una coppia di primitive di firma e verifica è utilizzata negli schemi di firma definiti in questo documento ed è specificata qui: primitiva di firma RSA versione 1 (RSASP1, RSA Signature Primitive, version 1) / primitiva di verifica RSA versione 1 (RSAVP1, RSA Verification Primitive, version 1).
Le primitive qui definite sono identiche alla primitiva di firma per fattorizzazione di interi usando RSA versione 1 (IFSP-RSA1) / primitiva di verifica per fattorizzazione di interi usando RSA versione 1 (IFVP-RSA1) in IEEE 1363 [IEEE1363] (ad eccezione dell'aggiunta del supporto per RSA multi-primo), e sono compatibili con PKCS #1 v1.5.
L'operazione matematica principale in ogni primitiva è l'esponenziazione, come nelle primitive di cifratura e decifratura della sezione 5.1. RSASP1 e RSAVP1 sono identiche a RSADP e RSAEP, ad eccezione dei nomi dei parametri di input e output; sono distinte perché vengono utilizzate per scopi diversi.
5.2.1. RSASP1
RSASP1 (K, m)
Input (Input)
K chiave privata RSA, dove K ha una delle seguenti forme:
- coppia (n, d)
- quintupla (p, q, dP, dQ, qInv) e sequenza possibilmente vuota di triple (r_i, d_i, t_i), i = 3, ..., u
m rappresentante del messaggio, un intero compreso tra 0 e n - 1
Output (Output)
s rappresentante della firma, un intero compreso tra 0 e n - 1
Errore (Error)
"message representative out of range" (rappresentante del messaggio fuori intervallo)
Assunzione (Assumption)
La chiave privata RSA K è valida
Passi (Steps)
Passo 1. Se il rappresentante del messaggio m non è compreso tra 0 e n - 1, restituire "message representative out of range" e fermarsi.
Passo 2. Il rappresentante della firma s è calcolato come segue:
a. Se viene utilizzata la prima forma di K (n, d), sia s = m^d mod n.
b. Se viene utilizzata la seconda forma di K (p, q, dP, dQ, qInv) e (r_i, d_i, t_i), procedere come segue:
- Sia s_1 = m^dP mod p e s_2 = m^dQ mod q.
- Se u > 2, sia s_i = m^(d_i) mod r_i, i = 3, ..., u.
- Sia h = (s_1 - s_2) * qInv mod p.
- Sia s = s_2 + q * h.
- Se u > 2, sia R = r_1 e per i = 3 a u, eseguire:
- a. Sia R = R * r_(i-1).
- b. Sia h = (s_i - s) * t_i mod r_i.
- c. Sia s = s + R * h.
Passo 3. Restituire s.
Nota: Il passo 2.b può essere riscritto come un singolo ciclo, a condizione che l'ordine di p e q sia invertito. Tuttavia, per coerenza con PKCS #1 v2.0, i primi due numeri primi p e q sono trattati separatamente dai numeri primi aggiuntivi.
5.2.2. RSAVP1
RSAVP1 ((n, e), s)
Input (Input)
(n, e) chiave pubblica RSA
s rappresentante della firma, un intero compreso tra 0 e n - 1
Output (Output)
m rappresentante del messaggio, un intero compreso tra 0 e n - 1
Errore (Error)
"signature representative out of range" (rappresentante della firma fuori intervallo)
Assunzione (Assumption)
La chiave pubblica RSA (n, e) è valida
Passi (Steps)
Passo 1. Se il rappresentante della firma s non è compreso tra 0 e n - 1, restituire "signature representative out of range" e fermarsi.
Passo 2. Sia m = s^e mod n.
Passo 3. Restituire m.
6. Panoramica degli schemi (Overview of Schemes)
Uno schema (Scheme) combina primitive crittografiche e altre tecniche per raggiungere un particolare obiettivo di sicurezza. Questo documento specifica due tipi di schemi: schemi di cifratura (Encryption Schemes) e schemi di firma con appendice (Signature Schemes with Appendix).
Gli schemi specificati in questo documento hanno una portata limitata, poiché le loro operazioni comprendono solo i passaggi di elaborazione dei dati utilizzando una chiave pubblica o privata RSA, e non includono i passaggi di ottenimento o verifica delle chiavi. Pertanto, oltre alle operazioni dello schema, le applicazioni includeranno generalmente operazioni di gestione delle chiavi (Key Management Operations) attraverso le quali le parti possono selezionare le chiavi pubbliche e private RSA per le operazioni dello schema. Le operazioni aggiuntive specifiche e altri dettagli sono al di fuori dell'ambito di questo documento.
Come nel caso delle primitive crittografiche (Sezione 5), la specifica delle operazioni dello schema presuppone che gli input soddisfino determinate condizioni, in particolare che le chiavi pubbliche e private RSA siano valide. Pertanto, quando le chiavi non sono valide, il comportamento delle implementazioni non è specificato. L'implicazione di questo comportamento non specificato dipende dall'applicazione. Gli approcci possibili per affrontare il problema della validazione delle chiavi includono: validazione esplicita delle chiavi da parte dell'applicazione; validazione delle chiavi all'interno di un'infrastruttura a chiave pubblica; e assegnazione della responsabilità di eseguire operazioni con chiavi non valide alla parte che ha generato le chiavi.
Una pratica crittografica generalmente buona è utilizzare una data coppia di chiavi RSA in un singolo schema. Ciò evita il rischio che una vulnerabilità in uno schema possa compromettere la sicurezza di un altro, e può essere essenziale per mantenere la sicurezza dimostrabile (Provable Security). Sebbene RSAES-PKCS1-v1_5 (Sezione 7.2) e RSASSA-PKCS1-v1_5 (Sezione 8.2) siano stati tradizionalmente utilizzati insieme senza interazioni avverse note (infatti, questo è il modello introdotto con PKCS #1 v1.5), questo uso combinato di coppie di chiavi RSA NON È RACCOMANDATO (NOT RECOMMENDED) per le nuove applicazioni.
Per illustrare il rischio associato all'uso di una coppia di chiavi RSA in più schemi, si supponga che una coppia di chiavi RSA sia utilizzata sia per RSAES-OAEP (Sezione 7.1) che per RSAES-PKCS1-v1_5. Sebbene RSAES-OAEP sia di per sé resistente agli attacchi, un attaccante potrebbe essere in grado di sfruttare una debolezza in un'implementazione RSAES-PKCS1-v1_5 per recuperare messaggi cifrati con uno dei due schemi. Un altro esempio, si supponga che una coppia di chiavi RSA sia utilizzata sia per RSASSA-PSS (Sezione 8.1) che per RSASSA-PKCS1-v1_5. In tal caso, la prova di sicurezza di RSASSA-PSS non sarebbe più sufficiente, poiché la prova non tiene conto della possibilità che le firme possano essere generate utilizzando il secondo schema. Considerazioni simili possono applicarsi se una coppia di chiavi RSA viene utilizzata per uno degli schemi definiti qui e una variante definita altrove.
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):
-
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.
-
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
-
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)
-
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):
-
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.
-
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)
-
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.
-
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.
8. Schema di firma con appendice (Signature Scheme with Appendix)
Uno schema di firma con appendice (Signature Scheme with Appendix) è composto da un'operazione di generazione della firma e un'operazione di verifica della firma, dove l'operazione di generazione della firma genera una firma da un messaggio utilizzando la chiave privata RSA del firmatario, e l'operazione di verifica della firma verifica l'autenticità della firma utilizzando la chiave pubblica RSA del firmatario.
Per firmare un messaggio M, il firmatario applica un'operazione di codifica del messaggio a M per generare un messaggio codificato EM, quindi applica la primitiva di firma per produrre una firma S. Per verificare una firma S, il verificatore applica la primitiva di verifica a S per recuperare il messaggio codificato EM, quindi applica l'operazione di verifica per determinare se la firma è valida per il messaggio.
Due schemi di firma sono specificati in questo documento: RSASSA-PSS e RSASSA-PKCS1-v1_5.
Sebbene non obbligatorio, RSASSA-PSS è raccomandato per le nuove applicazioni. RSASSA-PKCS1-v1_5 è incluso per la compatibilità con le applicazioni esistenti.
8.1. RSASSA-PSS
RSASSA-PSS combina le primitive RSASP1 e RSAVP1 (Sezione 5.2) con il metodo di codifica EMSA-PSS. Si basa sullo schema di firma probabilistica (Probabilistic Signature Scheme, PSS) proposto da Bellare e Rogaway [RSARABIN] [PSS].
La sicurezza di PSS si basa sulla difficoltà del problema RSA e sul modello oracle casuale del MGF. È stato dimostrato che, sotto il modello oracle casuale, se il MGF si comporta come un oracle casuale e il problema RSA è difficile, allora lo schema di firma PSS è sicuro contro gli attacchi a messaggio scelto (Chosen Message Attack).
RSASSA-PSS non è deterministico: per un dato messaggio, possono essere generate più firme possibili. Ciò è dovuto all'inclusione di un valore di sale casuale durante l'operazione di generazione della firma.
8.1.1. Operazione di generazione della firma (Signature Generation Operation)
RSASSA-PSS-SIGN (K, M)
Input (Input):
- K: chiave privata RSA del firmatario
- M: messaggio da firmare, una stringa di ottetti di lunghezza arbitraria
Output (Output):
- S: firma, una stringa di ottetti di lunghezza k, dove k è la lunghezza in ottetti del modulo RSA n
Errori (Errors):
- "message too long" (messaggio troppo lungo)
- "encoding error" (errore di codifica)
Passi (Steps):
-
Codifica EMSA-PSS: Applicare l'operazione di codifica EMSA-PSS al messaggio M per generare un messaggio codificato EM di lunghezza ⌈(modBits-1)/8⌉ ottetti, dove modBits è la lunghezza in bit del modulo RSA n: EM = EMSA-PSS-ENCODE(M, modBits - 1). Se l'operazione di codifica restituisce "message too long" o "encoding error", restituire l'errore corrispondente e fermarsi.
-
Firma RSA:
- Convertire il messaggio codificato EM in un rappresentante del messaggio intero m: m = OS2IP(EM)
- Applicare la primitiva di firma RSASP1: s = RSASP1(K, m)
- Convertire il rappresentante della firma s in una firma S di lunghezza k: S = I2OSP(s, k)
-
Restituire la firma S.
8.1.2. Operazione di verifica della firma (Signature Verification Operation)
RSASSA-PSS-VERIFY ((n, e), M, S)
Input (Input):
- (n, e): chiave pubblica RSA del firmatario
- M: messaggio, una stringa di ottetti di lunghezza arbitraria
- S: firma da verificare, una stringa di ottetti di lunghezza k
Output (Output):
- "valid signature" (firma valida) o "invalid signature" (firma non valida)
Passi (Steps):
-
Controllo di lunghezza: Se la lunghezza della firma S non è di k ottetti, restituire "invalid signature" e fermarsi.
-
Verifica RSA:
- Convertire la firma S in un rappresentante della firma intero s: s = OS2IP(S)
- Applicare la primitiva di verifica RSAVP1: m = RSAVP1((n, e), s). Se RSAVP1 restituisce "signature representative out of range", restituire "invalid signature" e fermarsi.
- Convertire il rappresentante del messaggio m in un messaggio codificato EM di lunghezza emLen = ⌈(modBits - 1)/8⌉: EM = I2OSP(m, emLen)
-
Verifica EMSA-PSS: Applicare l'operazione di verifica EMSA-PSS: Result = EMSA-PSS-VERIFY(M, EM, modBits - 1). Se Result = "consistent", restituire "valid signature"; altrimenti restituire "invalid signature".
8.2. RSASSA-PKCS1-v1_5
RSASSA-PKCS1-v1_5 combina le primitive RSASP1 e RSAVP1 (Sezione 5.2) con il metodo di codifica EMSA-PKCS1-v1_5. È compatibile con lo schema IFSSA in IEEE 1363 [IEEE1363], dove la funzione hash del valore DigestInfo viene utilizzata per generare il rappresentante del messaggio.
La sicurezza di RSASSA-PKCS1-v1_5 dipende dalla difficoltà del problema RSA. Sebbene non ci sia un attacco noto che riesca a violare questo schema, non esiste nemmeno una prova di sicurezza come per PSS.
8.2.1. Operazione di generazione della firma (Signature Generation Operation)
RSASSA-PKCS1-V1_5-SIGN (K, M)
I passi sono simili a RSASSA-PSS, ma utilizzano il metodo di codifica EMSA-PKCS1-v1_5
8.2.2. Operazione di verifica della firma (Signature Verification Operation)
RSASSA-PKCS1-V1_5-VERIFY ((n, e), M, S)
I passi sono simili a RSASSA-PSS, ma utilizzano il metodo di verifica EMSA-PKCS1-v1_5
9. Metodi di codifica per firme con appendice (Encoding Methods for Signatures with Appendix)
I metodi di codifica sono utilizzati per convertire un messaggio in un messaggio codificato, che può poi essere firmato dalle primitive di firma RSA. Questa sezione specifica due metodi di codifica: EMSA-PSS e EMSA-PKCS1-v1_5.
9.1. EMSA-PSS
EMSA-PSS (Encoding Method for Signatures with Appendix - Probabilistic Signature Scheme) è un metodo di codifica probabilistico che contiene casualità, e quindi può generare più messaggi codificati diversi per un dato messaggio.
9.1.1. Operazione di codifica (Encoding Operation)
EMSA-PSS-ENCODE (M, emBits)
Input (Input):
- M: messaggio da codificare, una stringa di ottetti di lunghezza arbitraria
- emBits: lunghezza massima in bit del messaggio codificato, almeno 8hLen + 8sLen + 9
Output (Output):
- EM: messaggio codificato, una stringa di ottetti di lunghezza emLen = ⌈emBits/8⌉
Passi (Steps):
-
Se la lunghezza di M è maggiore del limite di input della funzione hash Hash (2^61 - 1 ottetti per SHA-1), restituire "message too long" e fermarsi.
-
Sia mHash = Hash(M), una stringa di ottetti di lunghezza hLen.
-
Se emLen < hLen + sLen + 2, restituire "encoding error" e fermarsi.
-
Generare una stringa di ottetti casuale salt di lunghezza sLen.
-
Sia M' = (0x)00 00 00 00 00 00 00 00 || mHash || salt ; M' è una stringa di ottetti di lunghezza 8 + hLen + sLen.
-
Sia H = Hash(M'), una stringa di ottetti di lunghezza hLen.
-
Generare una stringa di ottetti PS composta da emLen - sLen - hLen - 2 ottetti zero.
-
Sia DB = PS || 0x01 || salt ; DB è una stringa di ottetti di lunghezza emLen - hLen - 1.
-
Sia dbMask = MGF(H, emLen - hLen - 1).
-
Sia maskedDB = DB ⊕ dbMask.
-
Impostare i 8emLen - emBits bit più a sinistra di maskedDB a zero.
-
Sia EM = maskedDB || H || 0xbc.
-
Restituire EM.
9.1.2. Operazione di verifica (Verification Operation)
EMSA-PSS-VERIFY (M, EM, emBits)
Input (Input):
- M: messaggio, una stringa di ottetti di lunghezza arbitraria
- EM: messaggio codificato da verificare, una stringa di ottetti di lunghezza emLen = ⌈emBits/8⌉
- emBits: lunghezza massima in bit del messaggio codificato
Output (Output):
- "consistent" (coerente) o "inconsistent" (incoerente)
Passi: (I passi di verifica sono l'inverso dei passi di codifica, verificando tutti i vincoli)
9.2. EMSA-PKCS1-v1_5
EMSA-PKCS1-v1_5 (Encoding Method for Signatures with Appendix - PKCS #1 v1.5) è un metodo di codifica deterministico che genera sempre lo stesso messaggio codificato per un dato messaggio.
EMSA-PKCS1-v1_5-ENCODE (M, emLen)
Input (Input):
- M: messaggio da codificare, una stringa di ottetti di lunghezza arbitraria
- emLen: lunghezza attesa del messaggio codificato (in ottetti), almeno tLen + 11, dove tLen è la lunghezza in ottetti del valore DigestInfo
Output (Output):
- EM: messaggio codificato, una stringa di ottetti di lunghezza emLen
Passi (Steps):
-
Applicare la funzione hash al messaggio M per generare il valore hash H: H = Hash(M). Se la funzione hash restituisce "message too long", restituire "message too long" e fermarsi.
-
Utilizzando la tecnica della nota nella Sezione 9.2, codificare il valore DigestInfo come T per la funzione hash.
-
Se emLen < tLen + 11, restituire "intended encoded message length too short" e fermarsi.
-
Generare una stringa di ottetti PS composta da emLen - tLen - 3 ottetti di valore 0xff.
-
Concatenare PS e altri padding per formare il messaggio codificato EM: EM = 0x00 || 0x01 || PS || 0x00 || T
-
Restituire EM.
10. Considerazioni di sicurezza
Le considerazioni di sicurezza sono trattate nelle varie parti di questo documento.
Aspetti principali della sicurezza
Lunghezza delle chiavi
La sicurezza delle chiavi RSA dipende in larga misura dalla dimensione del modulo. Le lunghezze minime raccomandate sono:
- 2048 bit: minimo attualmente raccomandato;
- 3072 bit: raccomandato per applicazioni ad alta sicurezza;
- 4096 bit: per chiavi di lunga durata o requisiti di sicurezza molto elevati.
Scelta dello schema
- RSAES-OAEP: DEVE essere supportato come schema di cifratura per le nuove applicazioni;
- RSASSA-PSS: schema di firma RACCOMANDATO per le nuove applicazioni;
- PKCS1-v1_5: mantenuto solo per compatibilità e presenta debolezze note.
Note di implementazione
- Generazione casuale: deve essere usato un generatore di numeri casuali crittograficamente sicuro.
- Attacchi laterali: l'implementazione dovrebbe prevenire attacchi temporali e analisi del consumo energetico.
- Gestione degli errori: i messaggi di errore per decrittazione e verifica dovrebbero essere uniformi, per evitare fughe di informazioni.
- Attacchi di padding oracle: RSAES-PKCS1-v1_5 è vulnerabile agli attacchi di Bleichenbacher e richiede particolare attenzione.
Funzioni hash
- Evitare: MD5 e SHA-1, che sono stati compromessi;
- Raccomandate: SHA-256, SHA-384 e SHA-512.
Uso delle chiavi
- Uso singolo: una coppia di chiavi RSA dovrebbe essere usata per un solo schema, cifratura oppure firma, e non per entrambi;
- Rotazione delle chiavi: sostituire le chiavi periodicamente;
- Protezione della chiave privata: memorizzare la chiave privata cifrata; l'uso di un Hardware Security Module (HSM) è una buona pratica.
Attacchi noti e difese
- Attacchi a testo cifrato scelto: RSAES-OAEP fornisce protezione;
- Attacchi a messaggio scelto: RSASSA-PSS fornisce protezione;
- Attacchi di Bleichenbacher: interessano RSAES-PKCS1-v1_5;
- Attacchi temporali: prestare attenzione quando si usano algoritmi a tempo costante e l'accelerazione CRT.
Si veda la sezione 6 per la discussione sull'evitare l'uso della stessa coppia di chiavi in più schemi.
Appendix A. Sintassi ASN.1 (ASN.1 Syntax)
Questa appendice riassume la sintassi ASN.1 utilizzata in questo documento. L'appendice C contiene il modulo ASN.1 completo.
A.1. RSA Key Representation (Rappresentazione delle chiavi RSA)
Questa sezione definisce la sintassi ASN.1 per le chiavi pubbliche e private RSA.
A.1.1. RSA Public Key Syntax (Sintassi della chiave pubblica RSA)
La chiave pubblica RSA deve essere rappresentata come tipo ASN.1 RSAPublicKey:
RSAPublicKey ::= SEQUENCE {
modulus INTEGER, -- n
publicExponent INTEGER -- e
}
Descrizione dei campi:
- modulus: Modulo RSA n
- publicExponent: Esponente della chiave pubblica RSA e
In una chiave pubblica RSA valida, il valore del modulo n deve essere il prodotto di u numeri primi dispari distinti r_i (i = 1, 2, ..., u), dove u >= 2, e l'esponente della chiave pubblica e deve essere un intero tra 3 e n - 1, che soddisfa GCD(e, λ(n)) = 1.
A.1.2. RSA Private Key Syntax (Sintassi della chiave privata RSA)
La chiave privata RSA deve essere rappresentata come tipo ASN.1 RSAPrivateKey:
RSAPrivateKey ::= SEQUENCE {
version Version,
modulus INTEGER, -- n
publicExponent INTEGER, -- e
privateExponent INTEGER, -- d
prime1 INTEGER, -- p
prime2 INTEGER, -- q
exponent1 INTEGER, -- d mod (p-1)
exponent2 INTEGER, -- d mod (q-1)
coefficient INTEGER, -- (inverse of q) mod p
otherPrimeInfos OtherPrimeInfos OPTIONAL
}
Version ::= INTEGER { two-prime(0), multi(1) }
(CONSTRAINED BY {
-- version must be multi if otherPrimeInfos present --
})
OtherPrimeInfos ::= SEQUENCE SIZE(1..MAX) OF OtherPrimeInfo
OtherPrimeInfo ::= SEQUENCE {
prime INTEGER, -- r_i
exponent INTEGER, -- d_i
coefficient INTEGER -- t_i
}
Descrizione dei campi:
- version: Numero di versione (two-prime indica RSA a due primi, multi indica RSA multi-primo)
- modulus: Modulo RSA n
- publicExponent: Esponente della chiave pubblica RSA e
- privateExponent: Esponente della chiave privata RSA d
- prime1: Primo fattore primo p
- prime2: Secondo fattore primo q
- exponent1: d mod (p-1)
- exponent2: d mod (q-1)
- coefficient: Coefficiente CRT qInv, (q^-1) mod p
- otherPrimeInfos: Opzionale, utilizzato per informazioni sui fattori primi aggiuntivi per RSA multi-primo
A.2. Scheme Identification (Identificazione dello schema)
Questa sezione definisce gli identificatori di oggetto (Object Identifiers) per i vari schemi definiti in questo documento.
A.2.1. RSAES-OAEP
Identificatore di oggetto per lo schema di cifratura RSAES-OAEP:
id-RSAES-OAEP OBJECT IDENTIFIER ::= { pkcs-1 7 }
Tipo di parametri di algoritmo per RSAES-OAEP:
RSAES-OAEP-params ::= SEQUENCE {
hashFunc [0] AlgorithmIdentifier DEFAULT sha1,
maskGenFunc [1] AlgorithmIdentifier DEFAULT mgf1SHA1,
pSourceFunc [2] AlgorithmIdentifier DEFAULT pSpecifiedEmpty
}
A.2.2. RSAES-PKCS1-v1_5
Identificatore di oggetto per lo schema di cifratura RSAES-PKCS1-v1_5:
id-RSAES-PKCS1-v1_5 OBJECT IDENTIFIER ::= { pkcs-1 1 }
Questo schema non ha parametri associati.
A.2.3. RSASSA-PSS
Identificatore di oggetto per lo schema di firma RSASSA-PSS:
id-RSASSA-PSS OBJECT IDENTIFIER ::= { pkcs-1 10 }
Tipo di parametri di algoritmo per RSASSA-PSS:
RSASSA-PSS-params ::= SEQUENCE {
hashAlgorithm [0] AlgorithmIdentifier DEFAULT sha1,
maskGenAlgorithm [1] AlgorithmIdentifier DEFAULT mgf1SHA1,
saltLength [2] INTEGER DEFAULT 20,
trailerField [3] INTEGER DEFAULT 1
}
A.2.4. RSASSA-PKCS1-v1_5
Lo schema di firma RSASSA-PKCS1-v1_5 utilizza i seguenti identificatori di oggetto per diverse funzioni hash:
sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
Questi identificatori di oggetto sono associati a funzioni hash specifiche.
Appendix B. Tecniche di supporto (Supporting Techniques)
Questa appendice contiene le specifiche delle tecniche di supporto utilizzate in questo documento, incluse le funzioni hash e le funzioni di generazione maschera.
B.1. Hash Functions (Funzioni hash)
Le funzioni hash vengono utilizzate per mappare messaggi di lunghezza arbitraria a output di lunghezza fissa. Le funzioni hash utilizzate negli schemi di questo documento devono soddisfare le seguenti proprietà:
- Resistenza alla preimmagine (Preimage Resistance): Dato un valore hash h, è computazionalmente non fattibile trovare un messaggio m tale che Hash(m) = h
- Resistenza alla seconda preimmagine (Second Preimage Resistance): Dato un messaggio m1, è computazionalmente non fattibile trovare un messaggio diverso m2 tale che Hash(m1) = Hash(m2)
- Resistenza alle collisioni (Collision Resistance): È computazionalmente non fattibile trovare due messaggi diversi qualsiasi m1 e m2 tali che Hash(m1) = Hash(m2)
Funzioni hash raccomandate
Questo documento raccomanda l'uso delle seguenti funzioni hash:
| Funzione hash | Lunghezza output(bit) | Lunghezza output(byte) | Stato |
|---|---|---|---|
| SHA-1 | 160 | 20 | ⚠️ Obsoleto(solo compatibilità all'indietro) |
| SHA-256 | 256 | 32 | ✅ Raccomandato |
| SHA-384 | 384 | 48 | ✅ Raccomandato |
| SHA-512 | 512 | 64 | ✅ Raccomandato |
| SHA-512/224 | 224 | 28 | ✅ Disponibile |
| SHA-512/256 | 256 | 32 | ✅ Disponibile |
Identificazione ASN.1 delle funzioni hash
Identificatore di algoritmo per SHA-256:
id-sha256 OBJECT IDENTIFIER ::= {
joint-iso-itu-t(2) country(16) us(840) organization(1)
gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1
}
Identificatore di algoritmo per SHA-384:
id-sha384 OBJECT IDENTIFIER ::= {
joint-iso-itu-t(2) country(16) us(840) organization(1)
gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2
}
Identificatore di algoritmo per SHA-512:
id-sha512 OBJECT IDENTIFIER ::= {
joint-iso-itu-t(2) country(16) us(840) organization(1)
gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3
}
B.2. Mask Generation Functions (Funzioni di generazione maschera)
Una funzione di generazione maschera (Mask Generation Function, MGF) prende come input una stringa di ottetti di lunghezza variabile e una lunghezza di output richiesta, e genera una stringa di ottetti di output della lunghezza specificata. Le funzioni di generazione maschera possono essere basate su funzioni hash o altre funzioni.
L'uso principale delle funzioni di generazione maschera è generare dati dall'aspetto casuale negli schemi di padding.
B.2.1. MGF1
MGF1 è una funzione di generazione maschera basata su una funzione hash. MGF1 (mgfSeed, maskLen) prende come input un seed di lunghezza variabile e una lunghezza di maschera richiesta, e produce una maschera della lunghezza specificata.
MGF1 (mgfSeed, maskLen)
Input (Input)
mgfSeed Seed di generazione maschera, stringa di ottetti di lunghezza arbitraria
maskLen Lunghezza attesa della maschera(in ottetti)
Output (Output)
mask Maschera di lunghezza maskLen, stringa di ottetti
Errore (Error)
"mask too long" (maschera troppo lunga)
Passi (Steps)
-
Se maskLen > 2^32 * hLen, output "mask too long" e fermarsi.
-
Sia T una stringa di ottetti vuota.
-
Per il contatore C da 0 a ⌈maskLen / hLen⌉ - 1:
- Convertire il contatore C in una stringa di ottetti C di lunghezza 4: C = I2OSP(C, 4)
- Concatenare l'hash di mgfSeed e C a T: T = T || Hash(mgfSeed || C)
-
Produrre i primi maskLen ottetti di T come maschera.
Opzioni MGF1 (MGF1 Options)
La funzione hash predefinita di MGF1 è SHA-1. Per le nuove applicazioni, si raccomanda l'uso di SHA-256 o di una funzione hash superiore.
Identificazione ASN.1 di MGF1 con SHA-256:
id-mgf1 OBJECT IDENTIFIER ::= { pkcs-1 8 }
-- Il parametro di MGF1 è la funzione hash utilizzata
AlgorithmIdentifier { ALGORITHM:IOSet } ::= SEQUENCE {
algorithm ALGORITHM.&id({IOSet}),
parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL
}
Considerazioni sulla sicurezza per MGF
Nel modello dell'oracolo casuale, se la funzione hash sottostante si comporta bene, l'output di MGF1 è computazionalmente indistinguibile da una stringa veramente casuale. Ciò rende MGF1 adatto per l'uso in schemi come OAEP e PSS.
Appendix D. Cronologia delle revisioni di PKCS #1 (Revision History of PKCS #1)
Evoluzione delle versioni
PKCS #1 v1.5 (novembre 1993)
- Contenuto: Definizione degli schemi di base per la cifratura e la firma RSA
- Cifratura: RSAES-PKCS1-v1_5
- Firma: RSASSA-PKCS1-v1_5
- Stato: Ampiamente distribuito, ma presenta debolezze di sicurezza note
PKCS #1 v2.0 (settembre 1998, RFC 2437)
- Aggiunta: Schema di cifratura RSAES-OAEP
- Aggiunta: Schema di firma RSASSA-PSS
- Miglioramento: Introduzione di schemi sicuri basati su prove
- Conservazione: Schemi v1.5 per mantenere la compatibilità all'indietro
PKCS #1 v2.1 (giugno 2002, RFC 3447)
- Miglioramento: Aggiornamento delle specifiche RSAES-OAEP e RSASSA-PSS
- Aggiunta: Supporto per funzioni hash aggiuntive (SHA-256, SHA-384, SHA-512)
- Aggiunta: Modulo ASN.1 completo
- Chiarimento: Uso di RSA multi-primo
PKCS #1 v2.2 (ottobre 2012 / novembre 2016, RFC 8017)
- Miglioramento: Chiarimenti tecnici e correzioni di errata
- Aggiornamento: Descrizione migliorata delle considerazioni sulla sicurezza
- Aggiunta: Supporto per SHA-512/224 e SHA-512/256
- Stato: Versione corrente, pubblicata come RFC 8017
Riepilogo delle modifiche principali
- v1.5 → v2.0: Introduzione degli schemi OAEP e PSS dimostrabimente sicuri
- v2.0 → v2.1: Supporto migliorato per le funzioni hash e RSA multi-primo
- v2.1 → v2.2: Chiarimenti tecnici e aggiornamento delle raccomandazioni di sicurezza
- Trasferimento RFC: Dalla serie PKCS di RSA Labs alla serie RFC dell'IETF
Note sulle deprecazioni
- RFC 3447 (PKCS #1 v2.1) è obsoleto per questo documento (RFC 8017, PKCS #1 v2.2)
- RSAES-PKCS1-v1_5 è conservato solo per la compatibilità all'indietro, non raccomandato per nuove applicazioni
- SHA-1 non è più raccomandato a causa di attacchi di collisione noti
Note sulla compatibilità
Sebbene tra le versioni siano stati introdotti nuovi schemi, per la compatibilità all'indietro:
- Gli schemi v1.5 sono mantenuti in tutte le versioni
- Gli schemi appena aggiunti (OAEP, PSS) coesistono con le vecchie implementazioni
- La sintassi ASN.1 mantiene la compatibilità all'indietro
Appendix E. Informazioni su PKCS (About PKCS)
Informazioni sugli standard di crittografia a chiave pubblica (Public-Key Cryptography Standards)
Gli standard di crittografia a chiave pubblica (PKCS, Public-Key Cryptography Standards) sono specifiche elaborate da RSA Laboratories in collaborazione con sviluppatori del settore industriale e accademico, con l'obiettivo di accelerare l'implementazione delle tecnologie di crittografia a chiave pubblica.
Panoramica della serie PKCS
La serie PKCS è stata inizialmente avviata da RSA Security Inc. (precedentemente RSA Data Security, Inc.) e include diversi standard:
| Standard | Nome | Stato |
|---|---|---|
| PKCS #1 | Specifiche di crittografia RSA | ✅ Questo documento (RFC 8017) |
| PKCS #3 | Standard di accordo di chiave Diffie-Hellman | - |
| PKCS #5 | Specifiche di crittografia basata su password | RFC 2898, RFC 8018 |
| PKCS #6 | Standard di sintassi di certificato esteso | Obsoleto |
| PKCS #7 | Standard di sintassi di messaggio crittografico | RFC 2315 (sostituito da CMS) |
| PKCS #8 | Specifica di sintassi di informazioni di chiave privata | RFC 5208, RFC 5958 |
| PKCS #9 | Tipi di attributi selezionati | RFC 2985 |
| PKCS #10 | Specifica di sintassi di richiesta di certificato | RFC 2986 |
| PKCS #11 | Interfaccia token crittografico (Cryptoki) | Standard OASIS |
| PKCS #12 | Standard di sintassi di scambio informazioni personali | RFC 7292 |
| PKCS #15 | Standard di formato informazioni token crittografico | ISO/IEC 7816-15 |
Significato storico di PKCS #1
PKCS #1 è uno degli standard più antichi e importanti della serie PKCS, che definisce il metodo di implementazione standardizzato della crittografia RSA:
- Adozione industriale: PKCS #1 è ampiamente adottato in protocolli come SSL/TLS, SSH, S/MIME, PGP, ecc.
- Impatto sulla standardizzazione: Ha influenzato standard internazionali come IEEE 1363, ISO/IEC 18033
- Contributo accademico: L'introduzione degli schemi OAEP e PSS ha promosso lo sviluppo della crittografia dimostrabimente sicura
Da RSA Labs all'IETF
A partire dalla metà degli anni 2000, gli standard della serie PKCS sono stati gradualmente trasferiti a organizzazioni di standardizzazione aperte:
- IETF: PKCS #1, #5, #7, #8, #9, #10, #12 convertiti in RFC
- OASIS: PKCS #11 (Cryptoki) convertito in standard OASIS
- ISO/IEC: PKCS #15 integrato nello standard ISO/IEC 7816
Questo documento (RFC 8017) rappresenta il trasferimento del controllo di PKCS #1 da RSA Labs all'IETF, garantendo la manutenzione e l'evoluzione continue di questo standard.
Ringraziamenti (Acknowledgements)
Lo sviluppo di PKCS #1 ha beneficiato di numerosi contributi dalla comunità crittografica, tra cui:
- Autori originali: Burt Kaliski, Jake Lacy
- Fondamenti teorici: Mihir Bellare, Phillip Rogaway (schemi OAEP e PSS)
- Contributori v2.0-v2.2: Jakob Jonsson, Burt Kaliski, Kathleen Moriarty, Andreas Rusch
- Revisione e feedback: Revisione estensiva dalla comunità IETF, RSA Labs e dal mondo accademico
Ulteriori informazioni
- Gruppo di lavoro PKCS dell'IETF:
https://datatracker.ietf.org/wg/pkcs/ - RSA Labs:
http://www.rsa.com/rsalabs/ - Archivio PKCS:
https://www.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs.htm