Введение
В этой лабораторной работе вы изучите основы обмена ключами Диффи-Хеллмана (Diffie-Hellman, DH) — краеугольного камня современной криптографии. Протокол DH позволяет двум сторонам, не имеющим предварительных знаний друг о друге, совместно установить общий секретный ключ через незащищенный канал связи. Этот общий секрет затем может использоваться для шифрования последующих сообщений с помощью симметричного шифра.
Вы будете использовать мощный инструмент командной строки openssl для симуляции всего процесса DH. Это включает генерацию публичных параметров, создание закрытых и открытых ключей для двух отдельных сторон, а также, наконец, вывод и проверку общего секрета. К концу этой лабораторной работы вы получите практическое понимание того, как работает это важнейшее криптографическое рукопожатие.
Принцип обмена ключами Диффи-Хеллмана
На этом шаге мы рассмотрим теоретический принцип обмена ключами Диффи-Хеллмана. На этом шаге не нужно выполнять никаких команд; цель состоит в том, чтобы понять концепцию перед ее реализацией.
Процесс работает следующим образом:
Согласование публичных параметров: Две стороны, назовем их Алиса и Боб, сначала договариваются о двух публичных числах: большом простом числе $p$ (модуль) и основании $g$ (генератор). Эти числа не являются секретными и могут передаваться по незащищенному каналу.
Генерация закрытого ключа:
- Алиса выбирает секретное целое частное число $a$. Она хранит это число в тайне.
- Боб выбирает секретное целое частное число $b$. Он хранит это число в тайне.
Вычисление открытого ключа:
- Алиса вычисляет свой открытый ключ $A$ по формуле: $A = g^a \mod p$. Она отправляет этот открытый ключ $A$ Бобу.
- Боб вычисляет свой открытый ключ $B$ по формуле: $B = g^b \mod p$. Он отправляет этот открытый ключ $B$ Алисе.
Вывод общего секрета:
- Алиса получает открытый ключ Боба $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, которые защищают данные в Интернете. Теперь у вас есть практическое понимание того, как две стороны могут установить защищенный канал связи, даже начиная с незащищенной сети.



