ЛР № 1. Прикладная криптография и протокол TLS

В пунктах с пометкой «самостоятельно» нужно составить и записать команды и их вывод, быть готовыми на защите пояснить сделанное.

1. Криптографические операции

Создайте файл message.txt с сообщением вида (со своими данными):

Студент Дмитрий Козлюк группы А-02-09.

1.1. Симметричное шифрование с заданным ключом

Получите 32 случайных байта для использования в качестве ключа и сохраните их в файле symmetric.key:

openssl rand -hex -out symmetric.key 32

Примечание. Утилита openssl объединяет очень разные функции. Как правило, первый аргумент openssl — команда (слово), затем следуют ключи команды (параметры с дефиса). Список команд можно получить через openssl help. По любой команде можно получить справку так: openssl <команда> -help.

Самостоятельно. Получите 16 случайных байтов для использования в качестве вектора инициализации (initialization vector, IV) и сохраните их в файле symmetric.iv.

Зашифруйте сообщение при помощи шифратора AES-256-CBC с полученным ключом и IV:

openssl enc -e -aes-256-cbc -K $(cat symmetric.key) -iv $(cat symmetric.iv) -in message.txt -out message.aes.raw.enc

Расшифруйте файл обратно:

openssl enc -d -aes-256-cbc -K $(cat symmetric.key) -iv $(cat symmetric.iv) -in message.aes.raw.enc -out message.aes.raw.dec 

Проверьте, что оригинал открытого текста совпадает с восстановленным:

Измерьте скорость AES-256-CBC на лабораторном стенде:

openssl speed aes-256-cbc

1.2. Симметричное шифрование с парольной фразой

В этом пункте качестве парольной фразы используется Dmitry Kozlyk. Нужно заменить её на своё имя и фамилию латиницей.

С помощью функции генерации ключа на основе пароля (password-based key derivation function, PBKDF) создайте ключ, IV и соль:

openssl enc -aes-256-cbc -pbkdf2 -P -k 'Dmitry Kozlyuk' -pbkdf2

Самостоятельно. Повторите процедуру несколько раз.

Зашифруйте сообщение при помощи шифратора AES-256-CBC с парольной фразы:

openssl enc -e -aes-256-cbc -pbkdf2 -p -k 'Dmitry Kozlyuk' -in message.txt -out message.aes.pass.enc

Расшифруйте файл обратно:

openssl enc -d -aes-256-cbc -pbkdf2 -p -k 'Dmitry Kozlyuk' -in message.aes.pass.enc -out message.aes.pass.dec 

Самостоятельно. Убедитесь, что расшифрованный текст совпадает с исходным.

Самостоятельно. Попробуйте расшифровать сообщение, указав неправильную парольную фразу. Что получится?

Самостоятельно. Какую роль играет соль (salt), которая генерируется и показывается с ключом -P? Сравните размер и содержимое зашифованных файлов. Как вы объясните отличия?

1.3. Генерация ключевых пар

Создайте закрытый (приватный) ключ Алисы размером 2048 бит для алгоритма RSA:

openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out alice.pri

Получите открытый ключ Алисы из закрытого:

openssl pkey -in alice.pri -out alice.pub -pubout

Просмотрите содержимое созданных файлов ключей.

Создайте еще две ключевые пары для Боба (bob.pri и bob.pub) и Чарли (charlie.pri и charlie.pub).

1.4. Асимметричное шифрование

Зашифруйте сообщение открытым ключом Алисы:

openssl pkeyutl -encrypt -pubin -inkey alice.pub -in message.txt -out message.rsa.enc

Расшифруйте сообщение закрытым ключом Алисы:

openssl pkeyutl -decrypt -inkey alice.pri -in message.rsa.enc -out message.rsa.dec

Самостоятельно. Проверьте, что восстановленный открытый текст соответствует оригиналу. Как openssl pkeyutl определяет, что нужно использовать алгоритм RSA?

Самостоятельно. Попробуйте расшифровать сообщение закрытым ключом Боба. Что получается?

Самостоятельно. Измерьте скорость RSA на лабораторном стенде.

1.5. Электронная подпись (ЭП)

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

openssl dgst -sha256 -sign alice.pri -out message.txt.sig message.txt

Выполните проверку ЭП, то есть расшифровку хеша открытым ключом и расшифрованного хеша c хешом, вычисленным по сообщению:

openssl dgst -sha256 -verify alice.pub -signature message.txt.sig message.txt

Самостоятельно. Измените message.txt и попробуйте снова проверить подпись. Что получается?

1.6. Самоподписанный сертификат

Создайте файл charlie.cnf следующего содержания:

extensions = req_ext

[req]
default_bits = 2048
default_md = sha256
prompt = no
encrypt_key = no
distinguished_name = dn

[dn]
C = RU
O = MIREA
OU = BK-536
CN = Dmitry Kozlyuk

[req_ext]
basicConstraints = critical,CA:TRUE

Файл конфигурации позволяет задать многочисленные сложные параметры, чего нельзя сделать через командную строку. Запрос на выпуск сертификата описывает первая по порядку секция, названная [req]. Она ссылается на секцию [dn], в которой описан владелец сертификата.

Глобальный параметр extensions = req_ext ссылается на секцию с расширениями. Корневой сертификат обязательно должен иметь расширение basicConstraints = CA:TRUE, то есть быть обозначен как CA.

Создайте запрос на подпись сертификата (certificate sign request, CSR) для Чарли:

openssl req -new -key charlie.pri -out charlie.csr -config charlie.cnf

Удовлетворите запрос Чарли, использовав для подписи его же закрытый ключ, то есть создайте для Чарли самоподписанный сертификат:

openssl x509 -req -signkey charlie.pri -in charlie.csr -out charlie.crt -days 365 -extfile charlie.cnf

Примечание. Мы используем единый файл charlie.cnf с параметрами владельца и расширений. На практике файлы могут быть разделелы: у создателя запроса конфигурация описывает только владельца сертификата, а у CA — расширения (так как CA решает, кому и для чего выписывает сертификат).

Просмотрите сертификат Чарли и убедитесь, что у него есть нужное расширение:

openssl x509 -in charlie.crt -text -noout

1.7. Формирование иерархии электронных сертификатов (PKI)

Самостоятельно. Создайте запрос на подпись сертификата Алисы. Используйте те же параметры, что у Чарли, но с CN = Alice. Сертификату нужны следующие расширения:

subjectAltName = DNS:alice.example.com
basicConstraints = CA:FALSE
extendedKeyUsage = serverAuth

Подпишите сертификат Алисы ключом Чарли:

openssl x509 -req -days 365 -extfile alice.cnf \
    -CAkey charlie.pri -CA charlie.crt -CAserial charlie.srl -CAcreateserial \
    -in alice.csr -out alice.crt

Здесь обратные косые черты использованы как символ переноса строк, в Windows следует вести одно длинную строку, убрав \, либо заменить эти символы на ^.

Самостоятельно. Просмотрите сертификат Алисы.

Проверьте подлинность сертификата Алисы:

openssl verify -verbose -issuer_checks -CAfile charlie.crt alice.crt

Самостоятельно. Создайте сертификат Боба, заверенный Чарли, и проверьте его подлинность. Сертификату нужны следующие расширения:

subjectAltName = DNS:bob.example.com
basicConstraints = CA:FALSE
extendedKeyUsage = clientAuth

2. Протокол TLS

2.1. Установка защищенного соединения

Запустите сервер TLS:

openssl s_server -accept 8443 -tls1_2 -www \
    -cert alice.crt -key alice.pri

Самостоятельно. Запустите в Wireshark захват TCP-пакетов через порт 8443.

Подключитесь к серверу TLS:

openssl s_client -connect localhost:8443 \
    -verify_return_error -verifyCAfile charlie.crt -verify_hostname alice.example.com

Отправьте сообщение по установленному каналу: введите его в работающем клиенте и нажмите Enter.

Завершние сеанс TLS: введите в работающем клиенте Q и нажмите Enter.

Самостоятельно: 1. Остановите захват пакетов в Wireshark и сохраните результат в файл. 2. Найдите пакет типа TLS ClientHello и соотнесите его поля с выводом openssl s_server. 3. Найдите пакет типа TLS ServerHello и соотнесите его поля с выводом openssl s_client.

Самостоятельно. Попробуйте подключиться к серверу, убрав у клиента параметр -verrifyCAfile charlie.crt. Что происходит и почему?

Самостоятельно. Попробуйте подключиться к серверу, изменив параметр: -verify_hostname bob.example.com. Что происходит и почему?

2.2. Клиентская аутентификация по сертификату (mutual TLS)

Запустите сервер TLS, требующий от клиента предъявить подлинный сертификат:

openssl s_server -accept 8443 -tls1_2 -www \
    -cert alice.crt -key alice.pri \
    -Verify 1 -verify_return_error -verifyCAfile charlie.crt

Самостоятельно. Попытайтесь подключиться к серверу так же, как раньше. Что изменилось?

Самостоятельно. Запустите в Wireshark захват TCP-пакетов через порт 8443.

Подключитесь к серверу TLS с предоставлением сертификата клиента:

openssl s_client -connect localhost:8443 \
    -verify_return_error -verifyCAfile charlie.crt -verify_hostname alice.example.com \
    -cert bob.crt -key bob.pri

Самостоятельно. Остановите захват пакетов в Wireshark. Какие новые сообщения появились в сеансе? Какие стороны их отправляют?

2.3. TLS 1.3

Самостоятельно. Повторите пункт 2.1, изменив у сервера ключ с -tls1_2 на -tls1_3.

Обратите внимание на версию TLS, указанную в полях Record Version и Message Version у сообщения ClientHello. Просмотрите элементы поля Extensions и найдите то, в котором передается версия TLS 1.3.

Самостоятельно. Попробуйте подключиться к серверу TLS 1.3, добавив клиенту ключ -tls1_2, то есть ограничив поддержку версией TLS 1.2. Что происходит и почему?

2.4. Зашифрованный ClientHello (ECH)

Убедитесь, что версия OpenSSL не ниже 4.x:

openssl version

Внимание! Пункт требует OpenSSL 4.x. На учебных стендах установлена подходящая версия. В пакетах большинства дистрибутивов Linux поставляется стабильная версия OpenSSL 3.x, которая не поддерживает ECH.

Сборка OpenSSL 4.x из исходного кода
# ~55 MB
wget https://github.com/openssl/openssl/releases/download/openssl-4.1.0/openssl-4.1.0.tar.gz
tar -xf openssl-4.1.0.tar.gz
cd openssl-4.1.0
./config --prefix=/opt/openssl/4.1.0 --openssldir=/opt/openssl/4.1.0 disable-shared disable-tests
make -j$(nproc)
# ~50 MB
sudo make install

Далее, чтобы использовать собранную программу openssl вместо системной:

export PATH=/opt/openssl/4.1.0/bin:$PATH

Создайте ключ для шифрования ClientHello:

openssl ech -public_name example.com -out ech.key

Извлеките конфигурацию клиента для использования ECH:

openssl ech -in ech.key -out ech.config

Самостоятельно. Запустите сервер, добавив параметр: -ech_key ech.key.

Самостоятельно. Запустите в Wireshark захват TCP-пакетов через порт 8443.

Самостоятельно. Запустите клиент, добавив параметр: -ech_config_list '...', где вместо ... должно стоять содержимое ech.config, но без PEM armour (---BEGIN ...---, ---END ...---) и в одну строку.

Добейтесь успешного подключения.

Самостоятельно. Остановите захват пакетов в Wireshark и сохраните результат в файл. В чем отличие сообщения ClientHello по сравнению с предыдущими пунктами?