#java #c #сокет
Здравствуйте. Подскажите пожалуйста. В учебных целях пишу SSL клиент. Читал RFC 5246, 6101 Вроде все понятно написано. Вот только есть проблема. Я пытался посмотреть как проходит соединение на практике. Считывал поток байтов, отправленный браузером, с сервер сокета. Дальше писал точно такой же поток байтов только с именем хоста yandex.ru. Подключался к хосту на 443 порту и отправлял поток байтов. Так же отправлял на сервер 32 случайных байта. В ответ сервер ничего не присылает а просто закрывает соединение. Использовать сторонние библиотеки не хочу. Интересно все сделать самому для лучшего понимания. Маюсь с этим уже 2 недели. Что я делаю не так? Как хотя бы начать handshake?
Ответы
Ответ 1
Легче всего будет практиковаться с конкретными инструментами. Запишите SSL-дамп c помощью Wireshark или Netmon. По дампу диалог между сервером и клиентом становится предельно прозрачным, если при этом внимательно изучать rfc, которым Вы руководствуетесь. Кроме того, Вам просто необходим еще один инструмент, называется OpenSSL. Он включает в себя набор утилит командной строки, которые помогут очень быстро нащупать верное направление при генерации ключей. Конечно, Вы можете генерировать их и сами, вручную, без дополнительных инструментов (хотя, не понимаю, зачем это Вам, но Вам обязательно скажут о плюсах использования подобных инструментов, я даже не буду касаться этой темы). Следующий шаг - потратьте немного времени на сертификат. Если Вам будет доступен сервер, для которого Вам будет известен сертификат с приватным ключом, то вы сможете расшифровать весь трафик (и сервера и клиента), это так же умеют делать Wireshark и Netmon. Такой сервер сейчас очень легко организовать прямо дома, все что Вам для этого нужно - Apache. Если Вы расшифруете трафик, то Вам будет понятно, правильно ли работает Ваша реализация, это автотестирование сэкономит Вам уйму времени. А вот теперь - самое интересное: Клиент посылает ClientHello, в котором передает на сервер случайные 32 байта, набор шифров и набор методов сжатия, с которыми он умеет обращаться. Сервер отвечает с ServerHello, в котором передает клиенту свои случайные 32 байта, шифр и метод сжатия, которые он выбрал из тех, что предложил клиент. Затем, сервер передает набор сертификатов (обычно - один) с публичным ключом и завершающее цепочку пустое сообщение DONE ("все хорошо, я готов к хендшейку"). Следующим сообщением, клиент посылает на сервер зашифрованный публичным ключом pre master secret. Расшифровать его можно только приватным ключом сервера, этим, по сути, и гарантируется безопасность диалога. Далее, клиент посылает пакет ChangeCipherSpec ("все хорошо, приступаем к общению с текущими параметрами безопасности"). Последнее сообщение клиента - пакет Finished, в котором он зашифровал 12-байтный проверочный хеш. Зашифровал уже ключом, который должен быть сгенерирован из pre master secret. В ответ, сервер посылает подряд 2 сообщения: аналогичный ChangeCipherSpec и свой Finished. На этом, хендшейк завершен. Теперь о ключах. Из pre master secret генерируется master secret. Из master secret генерируется последовательность key expansion, которая является донором для основных ключей, которыми кодируется и хэшируется трафик. Длина и наличие соответствующих ключей обуславливается выбранным шифром. Во всех SSL-RFC в приложении есть таблички, по которым эти параметры можно определить. Есть даже пример, на котором разбирается конкретный шифр. Это основной алгоритм. В деталях - уже конкретные реализации протоколов, например: у SSL3.0 и SSL3.1(TLS1.0) алгоритмы генерации различны, их описание есть в соответствующих RFC.Ответ 2
Считывал поток байтов, отправленный браузером, с сервер сокета. Дальше писал точно такой же поток байтов, только с именем хоста yandex.ru. Сервер рвёт соединение, так как нарушена процедура согласования (handshake). Клиент и сервер договариваются об использовании симметричного сессионного ключа. Этот ключ заново создаётся для каждой новой сессии на основе ключевой пары сторон и дополнительных случайно выбираемых параметров. Потому сервер и отказался принимать ключ, использованный в совершенно неизвестном для него захваченном сеансе связи, и разорвал соединение. 32 случайных байта были отправлены до завершения рукопожатия, а потому сервер принял их за корректное начало ответа клиента и ничего не отвечал, ожидая продолжения передачи.
Комментариев нет:
Отправить комментарий