Анализируем TLS не выходя из комы

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

TLS(Transport Layer Security) – криптографический протокол, основанный на протоколе SSL(Secure Sockets Layer), обеспечивающий, защищённую от прослушивания и подмены, передачу данных между узлами в сети интернет. Основной целью являлось получение относительно безопасного канала для осуществления покупок или управления банковским счётом. В современном интернете на TLS полагаются не только в коммерческой деятельности, но и при решении гораздо более общей задачи сохранения приватности информации. В основе криптобезопасности протокола лежат задачи: сокрытия информации, обнаружения модификации данных, проверки авторства, которые обеспечивают конфиденциальность, целостность и подлинность соединения(аутентификацию) соответственно. При использовании TLS, злоумышленнику будет доступна информация о подключении(хост, порт, тип используемого шифрования), частоте и количестве передаваемой информации. Кроме того, он может разорвать соединение, но обе стороны будут знать, что соединение было прервано третьей стороной.

В различных источниках TLS может быть расположен на различных уровнях модели OSI, что может вызвать непонимание. Нужно учитывать, что модель OSI – это концептуальная конструкция, которая пытается описать сетевую реальность. В действительности TLS состоит из двух протоколов: один работает внизу сеансового уровня(handshake, change cipher spec, alert), а другой работает наверху транспортного уровня(record layer). С технической точки зрения TLS работает на транспортном уровне. Это позволяет более высокоуровневым протоколам(HTTP, FTP, SMTP) работать без изменений.

Место TLS в модели OSI.

HIGH-LEVEL DESCRIPTION

После установления TCP-соединения и перед тем, как начать обмен по протоколу TLS, клиент и сервер должны согласовать некоторые параметры: версию протокола, шифронабор, а так же проверить сертификаты. Основные шаги процедуры создания защищённого сеанса связи:
1. Установление TCP-соединения.
2. Клиент предоставляет версию протокола и список поддерживаемых шифронаборов.
3. Сервер утверждает версию используемого протокола и выбирает из списка, предоставленного клиентом, наиболее надёжные шифронаборы среди тех, которые поддерживаются сервером, прикрепляет свой сертификат и отправляет ответ клиенту(при желании сервер может запросить клиентский сертификат).
4. Клиент, до начала передачи данных, проверяет валидность(аутентичность) полученного серверного сертификата и инициирует обмен ключами по протоколу Диффи-Хеллмана. Существует исторический метод передачи сгенерированного клиентом секрета на сервер, при помощи шифрования асимметричной криптосистемой RSA(используется ключ из сертификата сервера).
5. После установления общего секрета сервер обрабатывает присланное клиентом сообщение, сверяет MAC, и отправляет клиенту заключительное сообщение в зашифрованном виде.
6. Клиент расшифровывает полученное сообщение, сверяет MAC.
После этого соединение считается установленным и начинается обмен данными. При возникновении проблем на некоторых из вышеуказанных шагов подтверждение связи может завершиться с ошибкой, а безопасное соединение будет разорвано.

LOW-LEVEL DESCRIPTION

Чтобы установить контекст соединения клиент и сервер должны обменяться handshake-сообщениями. В TLS такой обмен происходит поверх обмена записями(records). Несколько handshake-сообщений могут быть переданы в одной записи(самый распространённый случай) или одно сообщение может быть разбито на несколько записей, передаваемых последовательно(теоретический вариант). Каждое handshake-сообщение содержит специальный заголовок, состоящий из четырёх байт. Первый байт обозначает код типа сообщения, три следующих байта – длину сообщения.
Спецификация предполагает, что клиент и сервер уже согласовали шифронабор null, без MAC и без сжатия. Это значит, что клиент и сервер будут обмениваться сообщениями в виде открытого текста без аутентификации.

Процесс установки безопасного соединения.

    ClientHello

    Первым сообщением из цепочки handshake-сообщений всегда является ClientHello(0x01). Сообщение содержит в себе:

    • Версию протокола – максимальную версию, которую готов поддерживать клиент.
    • 32 байта случайных данных – Client Random. Изначально, в спецификации рекомендовалось использовать первые 4 байта для передачи UNIX-timestamp, а оставшиеся 28 – заполнять результатом работы криптографического генератора псевдослучайных чисел.
    • Идентификатор TLS-сессии – SessionID. В случае если клиент хочет возобновить ранее установленную сессию.
    • Список шифронаборов, которые поддерживает клиент – Cipher Suites. Порядок шифронаборов в списке отражает их степень предпочтения клиентом(предпочтительные передаются первыми).
    • Список поддерживаемых методов сжатия – Compression Methods. Обычно в этом поле лишь одно значение – null.
    • Данные о расширениях протокола.
    struct {
        ProtocolVersion client_version;
        Random random;
        SessionID session_id;
        CipherSuite cipher_suites<2..2^16-2>;
        CompressionMethod compression_methods<1..2^8-1>;
        select (extensions_present) {
            case false:
                struct {};
            case true:
                Extension extensions<0..2^16-1>;
        };
    } ClientHello;
    

    Шифронабор это 16-битный идентификатор устанавливающий набор криптографических примитивов. Например, шифронабор TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 имеет идентификатор 0xc02b. Это означает, что для обмена ключами используется протокол Диффи-Хеллмана на эллиптических кривых с эфемерными ключами, в качестве алгоритма цифровой подписи выступает DSA на эллиптических кривых, AES c 256-битным ключом в режиме GCM в качестве симметричного блочного шифра в режиме аутентифицированного шифрования, SHA384 в качестве хэш-функции.
    Разберем ClientHello в деталях. В качестве сервера используем этот блог. В качестве сниффера небезызвестный Wireshark.

        Secure Sockets Layer
            TLSv1.2 Record Layer: Handshake Protocol: Client Hello
    16          Content Type: Handshake (22) - первый байт заголовка TLS-записи тип 22, сообщение handshake.
    03 03       Version: TLS 1.2 (0x0303) - версия TLS 1.2, что по сути SSL 3.3.
    00 dc       Length: 220 - длина пакета данных 220 байт.
                Handshake Protocol: Client Hello
    01              Handshake Type: Client Hello (1) - первый байт сообщения TLS тип 01, сообщение ClientHello.
    00 00 d8        Length: 216 - длина блока данных 216 байт.
    03 03           Version: TLS 1.2 (0x0303) - версия TLS 1.2.
                    Random - 32 байта случайных значений, ClientRandom, состоит из 4 байт unix-timestamp и 28 байт случайных данных.
    58 a9 f9 5f         GMT Unix Time: Feb 19, 2017 23:00:31.000000000 RTZ 2 (зима)
    b5 60 3a c0 ...     Random Bytes: b5603ac065209230b7704d848ad766c627af0a8d051f3a8661666911
    00              Session ID Length: 0 - длина поля SessionID так, как SessionID в данном сообщении не используется его длинна составляет 0 байт.
    00 38           Cipher Suites Length: 56 - длина поля со списком шифронаборов.
                    Cipher Suites (28 suites) - в данном случае указано 28 шифронаборов, по два байта на каждый из них.
    c0 2c               Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 (0xc02c)
    c0 2b               Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b)
    c0 30               Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030)
    c0 2f               Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (0xc02f)
    00 9f               Cipher Suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 (0x009f)
    00 9e               Cipher Suite: TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 (0x009e)
    c0 24               Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 (0xc024)
    c0 23               Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 (0xc023)
    c0 28               Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 (0xc028)
    c0 27               Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 (0xc027)
    c0 0a               Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)
    c0 09               Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA (0xc009)
    c0 14               Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (0xc014)
    c0 13               Cipher Suite: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA (0xc013)
    00 39               Cipher Suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA (0x0039)
    00 33               Cipher Suite: TLS_DHE_RSA_WITH_AES_128_CBC_SHA (0x0033)
    00 9d               Cipher Suite: TLS_RSA_WITH_AES_256_GCM_SHA384 (0x009d)
    00 9c               Cipher Suite: TLS_RSA_WITH_AES_128_GCM_SHA256 (0x009c)
    00 3d               Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA256 (0x003d)
    00 3c               Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA256 (0x003c)
    00 35               Cipher Suite: TLS_RSA_WITH_AES_256_CBC_SHA (0x0035)
    00 2f               Cipher Suite: TLS_RSA_WITH_AES_128_CBC_SHA (0x002f)
    00 0a               Cipher Suite: TLS_RSA_WITH_3DES_EDE_CBC_SHA (0x000a)
    00 6a               Cipher Suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256 (0x006a)
    00 40               Cipher Suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA256 (0x0040)
    00 38               Cipher Suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA (0x0038)
    00 32               Cipher Suite: TLS_DHE_DSS_WITH_AES_128_CBC_SHA (0x0032)
    00 13               Cipher Suite: TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA (0x0013)
    01              Compression Methods Length: 1 - длина поля методов сжатия.
    00              Compression Methods (1 method) - 00 - null, клиент не поддерживает сжатие.
    00 77           Extensions Length: 119 - длина поля расширений, далее следует список расширений клиента
                    Extension: server_name
                    Extension: status_request
                    Extension: elliptic_curves
                    Extension: ec_point_formats
                    Extension: signature_algorithms
                    Extension: SessionTicket TLS
                    Extension: Application Layer Protocol Negotiation
                    Extension: Extended Master Secret
                    Extension: Unknown 21760
                    Extension: renegotiation_info
    

    После отправки сообщения ClientHello клиент ждет сообщение ServerHello. Любое handshake-сообщение кроме ServerHello должно расцениваться как фатальная ошибка.

    ServerHello

    Если сервер успешно обработал ClientHello, то он должен ответить ServerHello в котором содержатся следующие данные:

    • Версию протокола, которую будут использовать клиент и сервер.
    • 32 байта случайных данных – Server Random.
    • Идентификатор сессии – SessionID для текущего соединения.
    • Выбранный сервером шифронабор(cipher suite) из предложенных клиентом.
    • Выбранный сервером метод сжатия, скорее всего это null.
    • Данные о расширениях протокола.
    struct {
        ProtocolVersion server_version;
        Random random;
        SessionID session_id;
        CipherSuite cipher_suite;
        CompressionMethod compression_method;
        select (extensions_present) {
            case false:
                struct {};
            case true:
                Extension extensions<0..2^16-1>;
        };
    } ServerHello;
    
        Secure Sockets Layer
            TLSv1.2 Record Layer: Handshake Protocol: Server Hello
    16          Content Type: Handshake (22) - первый байт заголовка TLS-записи тип 22, сообщение handshake.
    03 03       Version: TLS 1.2 (0x0303) - версия TLS 1.2.
    00 50       Length: 80 - длина пакета данных 80 байт.
                Handshake Protocol: Server Hello
    02              Handshake Type: Server Hello (2) - первый байт сообщения TLS тип 02, сообщение ServerHello.
    00 00 4c        Length: 76 - длина блока данных 216 байт.
    03 03           Version: TLS 1.2 (0x0303) - версия TLS 1.2.
                    Random - 32 байта случайных значений, ServerRandom, состоит из 4 байт unix-timestamp и 28 байт случайных данных.
    6a 31 50 83         GMT Unix Time: Jun 16, 2026 16:32:51.000000000 RTZ 2 (зима)
    f6 30 f3 d4 ...     Random Bytes: f630f3d49eeb979daaa31031ca9de723bc0f939bedda727eb647f227
    00              Session ID Length: 0 - длина поля SessionID так, как SessionID в данном сообщении не используется его длинна составляет 0 байт.
    c0 30           Cipher Suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (0xc030) - выбранный сервером шифронабор.
    00              Compression Method: null (0) - выбранный алгоритм сжатия.
    00 24           Extensions Length: 36 - длина поля расширений, далее следует список расширений сервера.
                    Extension: server_name
                    Extension: renegotiation_info
                    Extension: ec_point_formats
                    Extension: SessionTicket TLS
                    Extension: Application Layer Protocol Negotiation
    

    Параметры переданные в Hello-соообщениях позволяют построить контекст для работы криптосистемы, которая будет обрабатывать защищённые TLS-записи на стороне сервера и клиента. Помимо ClientHello и ServerHello, установление соединения подразумевает обмен несколькими другими сообщениями. За отправкой ServerHello, со стороны сервера следует ряд других сообщений, состав и содержание этих сообщений зависят от выбранного сервером режима работы.

    Certificate

    Серверный сертификат, который содержит открытый ключ сервера. Это сообщение отправляется всегда, за исключением случаев, когда шифронабор предписывает handshake без сертификата(анонимный режим). В большинстве случаев клиенту будет передана цепочка сертификатов(certificate chain), для того, чтобы клиент смог построить цепочку доверия от сертификата сервера до корневого сертификата.

    struct {
        ASN.1Cert certificate_list<0..2^24-1>;
    } Certificate;
    
        Secure Sockets Layer
            TLSv1.2 Record Layer: Handshake Protocol: Certificate
    16          Content Type: Handshake (22) - первый байт заголовка TLS-записи тип 22, сообщение handshake.
    03 03       Version: TLS 1.2 (0x0303) - версия TLS 1.2.
    09 c7       Length: 2503 - длина пакета данных 2503 байт.
                Handshake Protocol: Certificate
    0b              Handshake Type: Certificate (11) - первый байт сообщения TLS тип 11, сообщение Certificate.
    00 09 c3        Length: 2499 - длина блока данных 2499 байт.
    00 09 c0        Certificates Length: 2496 - длина блока сертификатов.
                    Certificates (2496 bytes)
    00 05 24            Certificate Length: 1316 - длина данных первого сертификата.
    30 82 05 20 30 ...  Certificate: 3082052030820408a003020102021203e8f9d8f7071bc196... (id-at-commonName=cyberdeveloper.pro)
    00 04 96            Certificate Length: 1174 - длина данных первого сертификата.
    30 82 04 92 30 ...  Certificate: 308204923082037aa00302010202100a0141420000015385... (id-at-commonName=Let's Encrypt Authority X3,id-at-organizationName=Let's Encrypt,id-at-countryName=US)
    

    В данном сообщении сервер прислал нам два сертификата, первый сертификат принадлежит серверу, второй центру сертификации(Certificate Authority — CA). Клиент должен произвести ряд проверок для всей цепочки, таких как, проверку подписи, проверку имени и убедиться, что сертификат не отозван.

    ServerKeyExchange

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

    enum { dhe_dss, dhe_rsa, dh_anon, rsa, dh_dss, dh_rsa
          /* may be extended, e.g., for ECDH -- see [TLSECC] */
    } KeyExchangeAlgorithm;
    
    struct {
        opaque dh_p<1..2^16-1>;
        opaque dh_g<1..2^16-1>;
        opaque dh_Ys<1..2^16-1>;
    } ServerDHParams;     /* Ephemeral DH parameters */
    
    struct {
        select (KeyExchangeAlgorithm) {
            case dh_anon:
                ServerDHParams params;
            case dhe_dss:
            case dhe_rsa:
                ServerDHParams params;
                digitally-signed struct {
                    opaque client_random[32];
                    opaque server_random[32];
                    ServerDHParams params;
                } signed_params;
            case rsa:
            case dh_dss:
            case dh_rsa:
                struct {} ;
            /* may be extended, e.g., for ECDH -- see [TLSECC] */
        };
    } ServerKeyExchange;
    

    Из структуры сообщения видно, что подпись вычисляется для случайных данных клиента, случайных данных сервера и параметров протокола Диффи-Хеллмана.

        Secure Sockets Layer
            TLSv1.2 Record Layer: Handshake Protocol: Server Key Exchange
    16          Content Type: Handshake (22) - первый байт заголовка TLS-записи тип 22, сообщение handshake.
    03 03       Version: TLS 1.2 (0x0303) - версия TLS 1.2.
    01 4d       Length: 333 - длина пакета данных 333 байт.
                Handshake Protocol: Server Key Exchange
    0c              Handshake Type: Server Key Exchange (12) - первый байт сообщения TLS тип 12, сообщение ServerKeyExchange.
    00 01 49        Length: 329 - длина блока данных 329 байт.
                    EC Diffie-Hellman Server Params
    03                  Curve Type: named_curve (0x03) - тип эллиптической кривой.
    00 17               Named Curve: secp256r1 (0x0017) - название эллиптической кривой.
    41                  Pubkey Length: 65 - длина публичного ключа 65 байт.
    04 d5 1f a4 32 ...  Pubkey: 04d51fa432ea48fd4b0a6eb637eb9ca094cf435db5fa414b... - публичный ключ.
                        Signature Hash Algorithm: 0x0401
    04                      Signature Hash Algorithm Hash: SHA256 (4) - используемая хэш-функция.
    01                      Signature Hash Algorithm Signature: RSA (1) - используемый алгоритм подписи.
    01 00               Signature Length: 256 - длина цифровой подписи 256 байт.
    01 8d 6b 4e 22 ...  Signature: 018d6b4e22890292aba68596385948f1cec6f899b7a256e3... - значение подписи.
    

    CertificateRequest

    В TLS возможна двухсторонняя аутентификация. Сервер может запросить клиентский сертификат отослав сообщения CertificateRequest. Сообщение содержит:

    • Типы сертификатов, которые поддерживает сервер.
    • Список пар хэш-функия/алгоритм подписи, которыми сервер в состоянии проверить подпись на сертификате клиента.
    • Список имен удостоверяющих центров, ключи которых сервер будет использовать для проверки клиентского сертификата.
    struct {
        ClientCertificateType certificate_types<1..2^8-1>;
        SignatureAndHashAlgorithm supported_signature_algorithms<2^16-1>;
        DistinguishedName certificate_authorities<0..2^16-1>;
    } CertificateRequest;
    

    При подключении к этому блогу сервер не стал запрашивать у нас сертификат(что очевидно), поэтому мы остались без пакета. Некоторые следующие сообщения будут так же рассмотрены только для ознакомления.

    ServerHelloDone

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

    struct { } ServerHelloDone;
    
        Secure Sockets Layer
            TLSv1.2 Record Layer: Handshake Protocol: Server Hello Done
    16          Content Type: Handshake (22) - первый байт заголовка TLS-записи тип 22, сообщение handshake.
    03 03       Version: TLS 1.2 (0x0303) - версия TLS 1.2.
    00 04       Length: 4 - длина пакета данных 4 байта.
                Handshake Protocol: Server Hello Done
    0e              Handshake Type: Server Hello Done (14) - первый байт сообщения TLS тип 14, сообщение ServerHelloDone.
    00 00 00        Length: 0 - длина блока данных 0 байт.
    

    После отправки этого сообщения, сервер должен ожидать ответа от клиента.

    Certificate

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

    struct {
        ASN.1Cert certificate_list<0..2^24-1>;
    } Certificate;
    

    Если клиент не посылает никаких сертификатов или в процессе проверки произошли ошибки, сервер может по своему усмотрению, либо продолжить без аутентификации клиента, либо среагировать летальным оповещением(handshake failure alert).

    ClientKeyExchange

    Это сообщение клиент должен посылать всегда. С помощью этого сообщения будет установлен общий симметричный ключ, путем передачи секрета(premaster secret) зашифрованного публичным ключом сервера, или путем передачи параметров протокола Диффи-Хеллмана, которые позволят каждой из сторон согласовать общий секрет.

    struct {
        ProtocolVersion client_version;
        opaque random[46];
    } PreMasterSecret;
    
    struct {
        select (PublicValueEncoding) {
            case implicit: struct { };
            case explicit: opaque dh_Yc<1..2^16-1>;
        } dh_public;
    } ClientDiffieHellmanPublic;
    
    struct {
        select (KeyExchangeAlgorithm) {
            case rsa:
                EncryptedPreMasterSecret;
            case dhe_dss:
            case dhe_rsa:
            case dh_dss:
            case dh_rsa:
            case dh_anon:
                ClientDiffieHellmanPublic;
        } exchange_keys;
    } ClientKeyExchange;
    
        Secure Sockets Layer
            TLSv1.2 Record Layer: Handshake Protocol: Client Key Exchange
    16          Content Type: Handshake (22) - первый байт заголовка TLS-записи тип 22, сообщение handshake.
    03 03       Version: TLS 1.2 (0x0303) - версия TLS 1.2.
    00 46       Length: 70 - длина пакета данных 70 байт.
                Handshake Protocol: Client Key Exchange
    10              Handshake Type: Client Key Exchange (16) - первый байт сообщения TLS тип 16, сообщение ClientKeyExchange.
    00 00 42        Length: 66 - длина блока данных 0 байт.
                    EC Diffie-Hellman Client Params
    41                  Pubkey Length: 65 - длина публичного ключа 65 байт.
    04 8d 5f 95 a4 ...  Pubkey: 048d5f95a4b75ae51b1b534181581ed36cfed4550032b992... - публичный ключ.
    

    Публичный ключ Диффи-Хеллмана генерируется клиентом в соответствии с параметрами, переданными сервером в сообщении ServerKeyExchange. Серверные параметры Диффи-Хеллмана подписываются приватным ключом сервера, клиент проверяет подпись, используя публичный ключ сервера.

    CertificateVerify

    Данное сообщение передается только если был передан клиентский сертификат в сообщении Certificate. Оно содержит цифровую подпись всех переданных ранее handshake-сообщений. Такая подпись доказывает факт наличия приватного ключа, связанного с сертификатом, у клиента.

    struct {
        digitally-signed struct {
            opaque handshake_messages[handshake_messages_length];
        }
    } CertificateVerify;
    

    На этом этапе фаза переговоров считается законченной. Клиент и сервер имеют одинаковую последовательность байт(premaster secret) из которой они должны вычислить общий секрет(master secret).

    master_secret = PRF(pre_master_secret, "master secret", ClientHello.random + ServerHello.random);
    

    Здесь PRF – псевдослучайная функция, в TLS 1.2 построена на базе хеш-функции SHA-256, либо может быть использована более мощная хеш-функция, указанная в составе шифронабора. Общий секрет(master secret) всегда равен 48 байтам, в отличие от premaster secret, размер которого может меняться в зависимости от метода обмена ключами. На основе общего секрета(master secret) будет сгенерированы остальные необходимые для сессии ключи, с использованием той же псевдослучайной функции. Делается это следующим способом:

    1. Определяется количество байт, нужное для выбранного шифронабора.
    2. Получаем необходимое количество байт(key block).
    3. key_block = PRF(SecurityParameters.master_secret, "key expansion", SecurityParameters.server_random + SecurityParameters.client_random);
    4. Полученный key block разбивается на несколько частей, клиентские: ключ для вычисления MAC, ключ для шифрования, вектор инициализации, и серверные: ключ для вычисления MAC, ключ для шифрования, вектор инициализации.

    ChangeCipherSpec

    Это сообщение посылается как клиентом, так и сервером и предназначено для уведомления принимающей стороны о том, что последующие записи(records) будут защищены в соответствии с выбранным шифронабором. Это сообщение не является handshake-сообщением и поэтому имеет тип 20, а не 22.

    struct {
        enum { change_cipher_spec(1), (255) } type;
    } ChangeCipherSpec;
    
        Secure Sockets Layer
            TLSv1.2 Record Layer: Change Cipher Spec Protocol: Change Cipher Spec
    14          Content Type: Change Cipher Spec (20) - первый байт заголовка TLS-записи тип 20, сообщение ChangeCipherSpec.
    03 03       Version: TLS 1.2 (0x0303) - версия TLS 1.2.
    00 01       Length: 1 - длина пакета данных 4 байта.
    01          Change Cipher Spec Message - первый байт сообщения TLS тип 1, сообщение ChangeCipherSpec.
    

    Finished

    Последнее в блоке handshake-сообщений и первое зашифрованное сообщение. Также посылается обеими сторонами сразу за ChangeCipherSpec. Необходимо для подтверждения того, что клиент и сервер согласовали эти параметры именно друг с другом.
    Клиентское Finished-сообщение содержит хэш и MAC от всех предыдущих handshake-сообщений отправленных обеими сторонами. Серверное также содержит хэш и MAC от предыдущих сообщений, включая клиентское Finished.

    struct {
        opaque verify_data[verify_data_length];
    } Finished;
    
    verify_data = PRF(master_secret, finished_label, Hash(handshake_messages));
    

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

        Secure Sockets Layer
            TLSv1.2 Record Layer: Handshake Protocol: Encrypted Handshake Message
    16          Content Type: Handshake (22) - первый байт заголовка TLS-записи тип 22, сообщение handshake.
    03 03       Version: TLS 1.2 (0x0303) - версия TLS 1.2.
    00 28       Length: 40 - длина зашифрованных данных 40 байт.
    10 8b f1 82 ... Handshake Protocol: Encrypted Handshake Message - зашифрованная часть данных.
    

    После обмена узлами ChangeCipherSpec и Finished, защищенное соединение считается установленным и начинается обмен данными(Application Data).

    ApplicationData

    Данные этого сообщения зашифрованы, защищены MAC-кодом для предотвращения атак повторного воспроизведения(replay attack) и модификации данных. MAC вычисляется от MAC-ключа(полученного из key block), порядкового номера сообщения, длинны сообщения, содержания сообщения и двух константных строк. Включение порядкового номера в MAC, позволяет обнаружить попытки удалить сообщения или изменить их порядок.

        Secure Sockets Layer
            TLSv1.2 Record Layer: Application Data Protocol: http-over-tls
    17          Content Type: Application Data (23) - первый байт заголовка TLS-записи тип 23, сообщение ApplicationData.
    03 03       Version: TLS 1.2 (0x0303) - версия TLS 1.2.
    04 54       Length: 1108 - длина зашифрованных данных 1108 байт.
    6c dd ...   Encrypted Application Data: 6cddbe5287c45ddf97681ecdebff12ed0e910b1e80eb4d2d... - зашифрованная часть данных.
    

    Соединение остаётся открытым до тех пор, пока одна из сторон не отправит сообщение, предупреждающее о завершении(close notify).

    Alert

    Еще один из типов сообщений поддерживаемых TLS-записями. Эти сообщения содержат уровень серьезности и описание предупреждения.

    enum { warning(1), fatal(2), (255) } AlertLevel;
    
    enum {
        close_notify(0),
        unexpected_message(10),
        bad_record_mac(20),
        decryption_failed_RESERVED(21),
        record_overflow(22),
        decompression_failure(30),
        handshake_failure(40),
        no_certificate_RESERVED(41),
        bad_certificate(42),
        unsupported_certificate(43),
        certificate_revoked(44),
        certificate_expired(45),
        certificate_unknown(46),
        illegal_parameter(47),
        unknown_ca(48),
        access_denied(49),
        decode_error(50),
        decrypt_error(51),
        export_restriction_RESERVED(60),
        protocol_version(70),
        insufficient_security(71),
        internal_error(80),
        user_canceled(90),
        no_renegotiation(100),
        unsupported_extension(110),
        (255)
    } AlertDescription;
    
    struct {
        AlertLevel level;
        AlertDescription description;
    } Alert;
    

    Пример: если клиент обнаружил, что сертификат сервера отозван, он отправляет сообщение Alert, содержащим ошибку certificate_revoked. Предупреждения с уровнем fatal сообщают о немедленном прекращении сеанса. Узлы должны стереть данные связанные с текущим подключением. Данные сообщения отправляются в открытом виде до установки защищенного соединения, а после в зашифрованном.

    РЕЗЮМЕ

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

    ПОЛЕЗНЫЕ ССЫЛКИ:

    RFC-5246 – The Transport Layer Security (TLS) Protocol Version 1.2.
    How does SSL/TLS work – хорошие ответы на security stackexchange.
    Ключи, шифры, сообщения: как работает TLS – большое описание протокола на русском.
    Первые несколько миллисекунд HTTPS соединения – статья с хабра раз.
    Что такое TLS – статья с хабра два.

    Если вам нравятся мои статьи, можете следить за обновлениями с помощью E-Mail, Twitter, Facebook, а также канала в Telegram.