7. Key Exchange (Scambio di chiavi)
7. Key Exchange (Scambio di chiavi)
Lo scambio di chiavi (key exchange, kex) inizia con ciascuna parte che invia liste di nomi (name-lists) degli algoritmi supportati. Ciascuna parte ha un algoritmo preferito in ciascuna categoria, e si assume che la maggior parte delle implementazioni, in un dato momento, userà lo stesso algoritmo preferito. Ciascuna parte PUÒ indovinare quale algoritmo usa l'altra parte, e PUÒ inviare un pacchetto iniziale di scambio di chiavi secondo l'algoritmo, se appropriato per il metodo preferito.
L'ipotesi è considerata errata se:
-
l'algoritmo kex e/o l'algoritmo della chiave host è stato indovinato in modo errato (server e client hanno algoritmi preferiti diversi), oppure
-
se uno qualsiasi degli altri algoritmi non può essere concordato (la procedura è definita sotto nella Sezione 7.1).
Altrimenti, l'ipotesi è considerata corretta, e il pacchetto inviato in modo ottimistico DEVE essere gestito come il primo pacchetto di scambio di chiavi.
Tuttavia, se l'ipotesi era errata, e un pacchetto è stato inviato in modo ottimistico da una o entrambe le parti, tali pacchetti DEVONO essere ignorati (anche se l'errore nell'ipotesi non influirebbe sul contenuto del o dei pacchetti iniziali), e la parte appropriata DEVE inviare il pacchetto iniziale corretto.
Un metodo di scambio di chiavi usa autenticazione esplicita del server (explicit server authentication) se i messaggi di scambio di chiavi includono una firma o altra prova dell'autenticità del server. Un metodo di scambio di chiavi usa autenticazione implicita del server (implicit server authentication) se, per provare la sua autenticità, il server deve anche dimostrare di conoscere il segreto condiviso K, inviando un messaggio e un MAC corrispondente che il client può verificare.
Il metodo di scambio di chiavi definito da questo documento usa autenticazione esplicita del server. Tuttavia, metodi di scambio di chiavi con autenticazione implicita del server POSSONO essere usati con questo protocollo. Dopo uno scambio di chiavi con autenticazione implicita del server, il client DEVE attendere una risposta al suo messaggio di richiesta di servizio prima di inviare ulteriori dati.
7.1. Algorithm Negotiation (Negoziazione degli algoritmi)
Lo scambio di chiavi inizia con ciascuna parte che invia il pacchetto seguente:
byte SSH_MSG_KEXINIT
byte[16] cookie (random bytes)
name-list kex_algorithms
name-list server_host_key_algorithms
name-list encryption_algorithms_client_to_server
name-list encryption_algorithms_server_to_client
name-list mac_algorithms_client_to_server
name-list mac_algorithms_server_to_client
name-list compression_algorithms_client_to_server
name-list compression_algorithms_server_to_client
name-list languages_client_to_server
name-list languages_server_to_client
boolean first_kex_packet_follows
uint32 0 (reserved for future extension)
Ciascuna delle liste di nomi degli algoritmi DEVE essere un elenco separato da virgole di nomi di algoritmi (vedere Algorithm Naming in [SSH-ARCH] e informazioni aggiuntive in [SSH-NUMBERS]). Ciascun algoritmo supportato (consentito) DEVE essere elencato in ordine di preferenza, dal più al meno preferito.
Il primo algoritmo in ciascuna name-list DEVE essere l'algoritmo preferito (presunto). Ciascuna name-list DEVE contenere almeno un nome di algoritmo.
cookie
The 'cookie' MUST be a random value generated by the sender.
Its purpose is to make it impossible for either side to fully
determine the keys and the session identifier.
kex_algorithms
Key exchange algorithms were defined above. The first
algorithm MUST be the preferred (and guessed) algorithm. If
both sides make the same guess, that algorithm MUST be used.
Otherwise, the following algorithm MUST be used to choose a key
exchange method: Iterate over client's kex algorithms, one at a
time. Choose the first algorithm that satisfies the following
conditions:
+ the server also supports the algorithm,
+ if the algorithm requires an encryption-capable host key,
there is an encryption-capable algorithm on the server's
server_host_key_algorithms that is also supported by the
client, and
+ if the algorithm requires a signature-capable host key,
there is a signature-capable algorithm on the server's
server_host_key_algorithms that is also supported by the
client.
If no algorithm satisfying all these conditions can be found, the
connection fails, and both sides MUST disconnect.
server_host_key_algorithms
A name-list of the algorithms supported for the server host
key. The server lists the algorithms for which it has host
keys; the client lists the algorithms that it is willing to
accept. There MAY be multiple host keys for a host, possibly
with different algorithms.
Some host keys may not support both signatures and encryption
(this can be determined from the algorithm), and thus not all
host keys are valid for all key exchange methods.
Algorithm selection depends on whether the chosen key exchange
algorithm requires a signature or an encryption-capable host
key. It MUST be possible to determine this from the public key
algorithm name. The first algorithm on the client's name-list
that satisfies the requirements and is also supported by the
server MUST be chosen. If there is no such algorithm, both
sides MUST disconnect.
encryption_algorithms
A name-list of acceptable symmetric encryption algorithms (also
known as ciphers) in order of preference. The chosen
encryption algorithm to each direction MUST be the first
algorithm on the client's name-list that is also on the
server's name-list. If there is no such algorithm, both sides
MUST disconnect.
Note that "none" must be explicitly listed if it is to be
acceptable. The defined algorithm names are listed in Section
6.3.
mac_algorithms
A name-list of acceptable MAC algorithms in order of
preference. The chosen MAC algorithm MUST be the first
algorithm on the client's name-list that is also on the
server's name-list. If there is no such algorithm, both sides
MUST disconnect.
Note that "none" must be explicitly listed if it is to be
acceptable. The MAC algorithm names are listed in Section 6.4.
compression_algorithms
A name-list of acceptable compression algorithms in order of
preference. The chosen compression algorithm MUST be the first
algorithm on the client's name-list that is also on the
server's name-list. If there is no such algorithm, both sides
MUST disconnect.
Note that "none" must be explicitly listed if it is to be
acceptable. The compression algorithm names are listed in
Section 6.2.
languages
This is a name-list of language tags in order of preference
[RFC3066]. Both parties MAY ignore this name-list. If there
are no language preferences, this name-list SHOULD be empty as
defined in Section 5 of [SSH-ARCH]. Language tags SHOULD NOT
be present unless they are known to be needed by the sending
party.
first_kex_packet_follows
Indicates whether a guessed key exchange packet follows. If a
guessed packet will be sent, this MUST be TRUE. If no guessed
packet will be sent, this MUST be FALSE.
After receiving the SSH_MSG_KEXINIT packet from the other side,
each party will know whether their guess was right. If the
other party's guess was wrong, and this field was TRUE, the
next packet MUST be silently ignored, and both sides MUST then
act as determined by the negotiated key exchange method. If
the guess was right, key exchange MUST continue using the
guessed packet.
Dopo lo scambio di messaggi SSH_MSG_KEXINIT, viene eseguito l'algoritmo di scambio di chiavi. Può coinvolgere diversi scambi di pacchetti, come specificato dal metodo di scambio di chiavi.
Una volta che una parte ha inviato un messaggio SSH_MSG_KEXINIT per lo scambio o riscambio di chiavi, finché non ha inviato un messaggio SSH_MSG_NEWKEYS (Sezione 7.3), NON DEVE inviare alcun messaggio diverso da:
-
Messaggi generici del livello di trasporto (1 a 19) (ma SSH_MSG_SERVICE_REQUEST e SSH_MSG_SERVICE_ACCEPT NON DEVONO essere inviati);
-
Messaggi di negoziazione degli algoritmi (20 a 29) (ma ulteriori messaggi SSH_MSG_KEXINIT NON DEVONO essere inviati);
-
Messaggi specifici del metodo di scambio di chiavi (30 a 49).
Le disposizioni della Sezione 11 si applicano ai messaggi non riconosciuti.
Si noti tuttavia che durante un riscambio di chiavi (key re-exchange), dopo aver inviato un messaggio SSH_MSG_KEXINIT, ciascuna parte DEVE essere preparata a elaborare un numero arbitrario di messaggi che possono essere in volo prima di ricevere un messaggio SSH_MSG_KEXINIT dall'altra parte.
7.2. Output from Key Exchange (Output dello scambio di chiavi)
Lo scambio di chiavi produce due valori: un segreto condiviso K e un hash di scambio H. Le chiavi di crittografia e autenticazione sono derivate da questi. L'hash di scambio H dal primo scambio di chiavi è inoltre usato come identificatore di sessione (session identifier), che è un identificatore univoco per questa connessione. È usato dai metodi di autenticazione come parte dei dati firmati come prova di possesso di una chiave privata. Una volta calcolato, l'identificatore di sessione non cambia, anche se le chiavi sono successivamente riscambiate.
Ciascun metodo di scambio di chiavi specifica una funzione di hash usata nello scambio di chiavi. Lo stesso algoritmo di hash DEVE essere usato nella derivazione delle chiavi. Qui lo chiameremo HASH.
Le chiavi di crittografia DEVONO essere calcolate come HASH di un valore noto e K, come segue:
-
IV iniziale client verso server: HASH(K || H || "A" || session_id) (Qui K è codificato come mpint e "A" come byte e session_id come dati grezzi. "A" significa il singolo carattere A, ASCII 65).
-
IV iniziale server verso client: HASH(K || H || "B" || session_id)
-
Chiave di crittografia client verso server: HASH(K || H || "C" || session_id)
-
Chiave di crittografia server verso client: HASH(K || H || "D" || session_id)
-
Chiave di integrità client verso server: HASH(K || H || "E" || session_id)
-
Chiave di integrità server verso client: HASH(K || H || "F" || session_id)
I dati di chiave DEVONO essere presi dall'inizio dell'output dell'hash. Sono presi dall'inizio del valore di hash tanti byte quanti necessari. Se la lunghezza di chiave richiesta è maggiore dell'output di HASH, la chiave è estesa calcolando HASH della concatenazione di K e H e dell'intera chiave finora, e accodando i byte risultanti (tanti quanti ne genera HASH). Questo processo è ripetuto finché non è disponibile materiale di chiave sufficiente; la chiave è presa dall'inizio di questo valore. In altre parole:
K1 = HASH(K || H || X || session_id) (X is e.g., "A")
K2 = HASH(K || H || K1)
K3 = HASH(K || H || K1 || K2)
...
key = K1 || K2 || K3 || ...
Questo processo perderà entropia se la quantità di entropia in K è maggiore della dimensione dello stato interno di HASH.
7.3. Taking Keys Into Use (Attivazione delle chiavi)
Lo scambio di chiavi termina con ciascuna parte che invia un messaggio SSH_MSG_NEWKEYS. Questo messaggio è inviato con le vecchie chiavi e algoritmi. Tutti i messaggi inviati dopo questo messaggio DEVONO usare le nuove chiavi e algoritmi.
Quando questo messaggio è ricevuto, le nuove chiavi e algoritmi DEVONO essere usati per la ricezione.
Lo scopo di questo messaggio è garantire che una parte sia in grado di rispondere con un messaggio SSH_MSG_DISCONNECT che l'altra parte possa comprendere se qualcosa va storto nello scambio di chiavi.
byte SSH_MSG_NEWKEYS