Алгоритм шифрования Diffie-Hellman (RFC 4419, 4253(8))

видео с разъяснениями

SSH-2 использует алгоритм Diffie-Hellman как основной (и единственный) метод обмена ключами.

Алгоритм Диффи-Хеллмана работает следующим образом:

  • Предположим, что двум абонентам (P1 и P2) требуется установить между собой безопасное соединение, для которого необходимо согласовать ключ шифрования.
  • P1 и P2 принимают к использованию два больших целых числа a и b, причем 1 < a < b.
  • P1 выбирает случайное число i и вычисляет I = ai mod b. P1 передает I абоненту P2.
  • P2 выбирает случайное число j и вычисляет J = aj mod b. P2 передает J абоненту P1.
  • P1 вычисляет k1 = Ji mod b.
  • P2 вычисляет k2 = Ij mod b.
  • Имеем k1 = k2 = ai*j mod b, следовательно, k1 и k2 являются секретными ключами, предназначенными для использования при передаче других данных.

Примечание:
В приведенных выше уравнениях "mod" означает остаток. Например, 12 mod 10 = 2. Два - это остаток от деления 12 на 10.

8. Diffie-Hellman Key Exchange (RFC 4253)

The Diffie-Hellman (DH) key exchange provides a shared secret that cannot be determined by either party alone. The key exchange is combined with a signature with the host key to provide host authentication. This key exchange method provides explicit server authentication as defined in Section 7.

Для передачи ключа выполняются следующие шаги:
где
C - клиент;
S - сервер;
p - большое целое число;
g is a generator for a subgroup of GF(p);
q is the order of the subgroup;
V_S - идентификационная строка сервера;
V_C - идентификационная строка клиента;
K_S - открытый ключ хоста сервера;
I_C is C's SSH_MSG_KEXINIT message
I_S is S's SSH_MSG_KEXINIT message that have been exchanged before this part begins.

1. C генерирует случайное число x (1 < x < q) и вычисляет e = g^x mod p. C отправляет e на S.

2. S генерирует случайное число y (0 < y < q) и вычисляет f = g^y mod p. S получает e. Он вычисляет K = e^y mod p, H = hash(V_C || V_S || I_C || I_S || K_S || e || f || K) (эти элементы закодированы согласно их типам; см ниже) и ставит подпись s на H своим закрытым ключом хоста. S отправляет (K_S || f || s) на C. Операция подписания может вызвать вторую операцию хеширования.

3. C проверяет что K_S действительно является ключём хоста для S (используя сертификаты или локальную БД). C также может принять ключ без проверки; однако, такие действия делают протокол небезопасным против активных атак (но сейчас они часто используются из практических соображений во многих окружениях). Далее C вычисляет K = f^x mod p, H = hash(V_C || V_S || I_C || I_S || K_S || e || f || K) и проверяет подпись s на H.

Значения e или f которые не находятся в диапазоне [1, p-1] не должны быть отправлены или приняты любой из сторон. Если это условие будет нарушено, то обмен ключом закончится неудачей.