Базовый обмен ключами Диффи-Хеллмана в криптографии

LinuxBeginner
Практиковаться сейчас

Введение

В этой лабораторной работе вы изучите основы обмена ключами Диффи-Хеллмана (Diffie-Hellman, DH) — краеугольного камня современной криптографии. Протокол DH позволяет двум сторонам, не имеющим предварительных знаний друг о друге, совместно установить общий секретный ключ через незащищенный канал связи. Этот общий секрет затем может использоваться для шифрования последующих сообщений с помощью симметричного шифра.

Вы будете использовать мощный инструмент командной строки openssl для симуляции всего процесса DH. Это включает генерацию публичных параметров, создание закрытых и открытых ключей для двух отдельных сторон, а также, наконец, вывод и проверку общего секрета. К концу этой лабораторной работы вы получите практическое понимание того, как работает это важнейшее криптографическое рукопожатие.

Принцип обмена ключами Диффи-Хеллмана

На этом шаге мы рассмотрим теоретический принцип обмена ключами Диффи-Хеллмана. На этом шаге не нужно выполнять никаких команд; цель состоит в том, чтобы понять концепцию перед ее реализацией.

Процесс работает следующим образом:

  1. Согласование публичных параметров: Две стороны, назовем их Алиса и Боб, сначала договариваются о двух публичных числах: большом простом числе p (модуль) и основании g (генератор). Эти числа не являются секретными и могут передаваться по незащищенному каналу.

  2. Генерация закрытого ключа:

    • Алиса выбирает секретное целое частное число a. Она хранит это число в тайне.
    • Боб выбирает секретное целое частное число b. Он хранит это число в тайне.
  3. Вычисление открытого ключа:

    • Алиса вычисляет свой открытый ключ A по формуле: A = g^a \mod p. Она отправляет этот открытый ключ A Бобу.
    • Боб вычисляет свой открытый ключ B по формуле: B = g^b \mod p. Он отправляет этот открытый ключ B Алисе.
  4. Вывод общего секрета:

    • Алиса получает открытый ключ Боба B и вычисляет общий секрет S, используя свой собственный закрытый ключ a: S = B^a \mod p.
    • Боб получает открытый ключ Алисы A и вычисляет общий секрет S, используя свой собственный закрытый ключ b: S = A^b \mod p.

Благодаря свойствам модульной арифметики, и Алиса, и Боб получат абсолютно одинаковое значение для S.

  • Вычисление Алисы: S = (g^b \mod p)^a \mod p = g^{ba} \mod p
  • Вычисление Боба: S = (g^a \mod p)^b \mod p = g^{ab} \mod p

Перехватчик в канале может видеть p, g, A и B, но не может легко вычислить закрытые ключи a или b. Эта сложность известна как проблема дискретного логарифмирования, которая лежит в основе безопасности обмена Диффи-Хеллмана.

На следующих шагах вы будете использовать openssl для выполнения этих действий.

Генерация параметров Диффи-Хеллмана

На этом шаге вы сгенерируете публичные параметры DH (p и g), которые будут использоваться обеими сторонами. Инструмент openssl может выполнить за вас сложную математику по поиску подходящего простого числа и генератора. Все операции в этой лабораторной работе будут выполняться в каталоге по умолчанию ~/project.

Используйте команду openssl dhparam для генерации параметров. Мы укажем длину ключа 2048 бит, что является распространенной и безопасной длиной для этой цели.

Выполните следующую команду в своем терминале:

openssl dhparam -out dhparam.pem 2048

Разберем эту команду:

  • openssl dhparam: Это вызывает инструмент управления параметрами DH в OpenSSL.
  • -out dhparam.pem: Этот флаг указывает, что результат должен быть сохранен в файл с именем dhparam.pem.
  • 2048: Это желаемая битовая длина простого модуля p.

Выполнение этой команды может занять минуту, поскольку она ищет сильное простое число. Во время работы вы увидите вывод, похожий на следующий:

Generating DH parameters, 2048 bit long safe prime

После завершения в вашем текущем каталоге будет создан файл с именем dhparam.pem. Этот файл содержит публичные параметры, которые обе стороны будут использовать для обмена ключами.

Генерация ключей Стороны А

На этом шаге вы смоделируете действия первой стороны, назовем ее "Сторона А". Сторона А будет использовать общие параметры DH из предыдущего шага для генерации своего закрытого ключа, а затем выведет соответствующий открытый ключ.

Сначала сгенерируем закрытый ключ Стороны А. Этот ключ соответствует секретному числу a из нашего теоретического примера. Мы будем использовать команду openssl genpkey, которая является утилитой общего назначения для генерации ключей.

Выполните следующую команду для генерации закрытого ключа Стороны А:

openssl genpkey -paramfile dhparam.pem -out a_private_key.pem
  • genpkey: Команда для генерации закрытого ключа.
  • -paramfile dhparam.pem: Это указывает genpkey использовать параметры из нашего файла dhparam.pem для создания DH-ключа.
  • -out a_private_key.pem: Это сохраняет сгенерированный закрытый ключ в файл a_private_key.pem.

Далее Стороне А необходимо вывести открытый ключ из закрытого ключа. Открытый ключ — это то, что будет передано Стороне Б.

Выполните эту команду для извлечения открытого ключа:

openssl pkey -in a_private_key.pem -pubout -out a_public_key.pem
  • pkey: Команда для управления открытыми и закрытыми ключами.
  • -in a_private_key.pem: Указывает входной закрытый ключ.
  • -pubout: Этот флаг предписывает команде вывести открытую часть ключа.
  • -out a_public_key.pem: Сохраняет полученный открытый ключ в файл a_public_key.pem.

Теперь у вас есть два новых файла: a_private_key.pem, который Сторона А должна хранить в секрете, и a_public_key.pem, который Сторона А отправит Стороне Б по незащищенному каналу.

Генерация ключей Стороны Б

На этом шаге вы выполните те же действия для второй стороны, назовем ее "Сторона Б". Сторона Б действует независимо от Стороны А, но использует те же публичные параметры DH из dhparam.pem.

Сначала сгенерируем закрытый ключ Стороны Б. Это соответствует секретному числу b в нашем теоретическом примере.

Выполните следующую команду:

openssl genpkey -paramfile dhparam.pem -out b_private_key.pem

Эта команда по структуре идентична команде для Стороны А, но мы сохраняем результат в файл b_private_key.pem для различения.

Далее, как и Сторона А, Сторона Б должна вывести свой открытый ключ из своего нового закрытого ключа.

Выполните эту команду для извлечения открытого ключа Стороны Б:

openssl pkey -in b_private_key.pem -pubout -out b_public_key.pem

На этом этапе в реальном обмене Сторона А имела бы открытый ключ Стороны Б (b_public_key.pem), а Сторона Б имела бы открытый ключ Стороны А (a_public_key.pem). Обе стороны сохранили свои соответствующие закрытые ключи в секрете. Теперь вы успешно смоделировали часть протокола, связанную с генерацией и обменом ключами.

Вычисление общего секрета

Это заключительный и самый важный шаг. Здесь обе стороны будут использовать свой собственный закрытый ключ и открытый ключ другой стороны для независимого вычисления общего секрета. Если протокол успешен, они обе получат абсолютно одинаковое секретное значение.

Сначала вычислим общий секрет с точки зрения Стороны А. Сторона А использует свой закрытый ключ (a_private_key.pem) и открытый ключ Стороны Б (b_public_key.pem).

Выполните следующую команду:

openssl pkeyutl -derive -inkey a_private_key.pem -peerkey b_public_key.pem -out a_shared_secret.bin
  • pkeyutl: Утилита для выполнения операций с открытыми ключами.
  • -derive: Это действие указывает утилите вывести общий секрет.
  • -inkey a_private_key.pem: Указывает собственный закрытый ключ Стороны А.
  • -peerkey b_public_key.pem: Указывает открытый ключ другой стороны (собеседника, "peer").
  • -out a_shared_secret.bin: Сохраняет полученный бинарный секрет в файл.

Далее вычислим общий секрет с точки зрения Стороны Б. Сторона Б использует свой закрытый ключ (b_private_key.pem) и открытый ключ Стороны А (a_public_key.pem).

Выполните следующую команду:

openssl pkeyutl -derive -inkey b_private_key.pem -peerkey a_public_key.pem -out b_shared_secret.bin

Теперь у вас есть два файла: a_shared_secret.bin и b_shared_secret.bin. Чтобы проверить успешность обмена ключами, эти два файла должны быть идентичны. Вы можете использовать команду cmp (compare) для проверки этого.

cmp a_shared_secret.bin b_shared_secret.bin

Если файлы идентичны, эта команда не выдаст никакого вывода и завершится тихо. Эта тишина означает успех!

Для более наглядного подтверждения вы также можете вычислить криптографический хеш обоих файлов. Хеши должны совпадать.

sha256sum *.bin

Вы должны увидеть вывод, где оба файла имеют абсолютно одинаковый хеш SHA256. Фактические значения хешей будут различаться при каждом запуске, но они должны быть идентичными для обоих файлов:

e3705a4ab5ae5d86f59dfe968f0177b49d5144e2d731dbd8d41b2eda318412ec  a_shared_secret.bin
e3705a4ab5ae5d86f59dfe968f0177b49d5144e2d731dbd8d41b2eda318412ec  b_shared_secret.bin

(Примечание: Ваши значения хешей будут отличаться от этого примера, но важно то, что хеши для a_shared_secret.bin и b_shared_secret.bin должны быть идентичными, что доказывает, что обе стороны вывели один и тот же общий секрет.)

Поздравляем, вы успешно выполнили обмен ключами Диффи-Хеллмана!

Резюме

В этой лабораторной работе вы успешно смоделировали полный обмен ключами Диффи-Хеллмана с использованием инструмента командной строки openssl. Вы получили практический опыт работы с фундаментальными шагами этого критически важного криптографического протокола.

Вы узнали, как:

  • Генерировать общие публичные параметры DH (openssl dhparam).
  • Создавать пары закрытого и открытого ключей для двух отдельных сторон на основе этих параметров (openssl genpkey и openssl pkey).
  • Выводить общий секрет из собственного закрытого ключа и открытого ключа собеседника (openssl pkeyutl -derive).
  • Проверять, что обе стороны независимо вычислили абсолютно одинаковый секрет, тем самым доказывая успешность обмена.

Этот процесс является основополагающим строительным блоком для систем безопасной связи, таких как TLS/SSL, которые защищают данные в Интернете. Теперь у вас есть практическое понимание того, как две стороны могут установить защищенный канал связи, даже начиная с незащищенной сети.