DTLS

2021-10-31  本文已影响0人  给艺艺一个未来

简介

DTLS:Datagram Transport Layer Security:数据报传输层安全。

背景

SSL:Secure Sockets Layer:安全套接层。为网络通信提供安全及数据完整性保障。SSL 3.0作为历史文献IETF通过RFC 6101发表。
TLS:Transport Layer Security:传输层安全。IETF将SSL标准化,即RFC 2246,并将其称为TLS。

SSL/TLS协议并不能用于UDP协议,但UDP同样有安全传输的需求,于是有了DTLS协议。DTLS基于TLS扩展,使之支持UDP协议。DTLS 1.0 基于 TLS 1.1,DTLS 1.2 基于 TLS 1.2。

概述

DTLS是一个保证传输安全的协议,DTLS采用加密保证数据机密性。

在《密码学简述》一文中提到:非对称加密的计算开销非常大,因此在一个会话通信中,采用对称加密的方式保证数据机密性更为合适,而非对称加密可以应用在对称加密的密钥分发、数字签名等方面。

DTLS使用非对称加密分发对称加密的密钥,即DTLS握手。DTLS握手完成后,即可使用对称加密的密钥进行加密通信。

DTLS的安全性在以下几个方面得到了保障:

DTLS由两部分组成:Record Layer 和 Handshake Protocol

DTLS Record Layer

Record Struct

   enum {
        change_cipher_spec(20), alert(21), handshake(22),
        application_data(23), (255)
      } ContentType;

   struct {
        ContentType type;
        ProtocolVersion version;
        uint16 epoch;                                     // New field
        uint48 sequence_number;                           // New field
        uint16 length;
        opaque fragment[DTLSPlaintext.length];
      } DTLSPlaintext;

      struct {
        ContentType type;
        ProtocolVersion version;
        uint16 epoch;                                     // New field
        uint48 sequence_number;                           // New field
        uint16 length;
        opaque fragment[DTLSCompressed.length];
      } DTLSCompressed;

      struct {
        ContentType type;
        ProtocolVersion version;
        uint16 epoch;                                     // New field
        uint48 sequence_number;                           // New field
        uint16 length;
        select (CipherSpec.cipher_type) {
          case block:  GenericBlockCipher;
          case aead:   GenericAEADCipher;                 // New field
        } fragment;
      } DTLSCiphertext;

Wireshark Capture

Figure 1: DTLS Capture
Figure 2: Handshake Message
Figure 3: Application Data

由此可见:

注:

Figure 4: Record Layer所处的协议栈位置

DTLS Handshake

握手是为了校验通信双方身份,并安全地协商密钥,因此在握手的过程会通过 Message 验证证书、协商加密算法和密钥参数、使用非对称加密交换对称密钥、并使用数字签名(MAC鉴权摘要)保证数据不被篡改。

DTLS 使用多种安全机制提供安全服务。

DTLS提供:序号(顺序),分段,重传 等机制以应对可能存在的需求。

DTLS定义了基于cookie验证的机制来预防Dos攻击。

Handshake Process

   Client                                          Server
   ------                                          ------

   ClientHello             -------->                           Flight 1

                           <-------    HelloVerifyRequest      Flight 2
                                       (contains cookie)

   ClientHello             -------->                           Flight 3
  (with cookie)

                                              ServerHello    \
                                             Certificate*     \
                                       ServerKeyExchange*      Flight 4
                                      [CertificateRequest]    /
                           <--------      ServerHelloDone    /

   [Certificate]                                             \
   ClientKeyExchange                                          \
   [CertificateVerify]                                         Flight 5
   [ChangeCipherSpec]                                         /
   Finished                -------->                         /

                                       [ChangeCipherSpec]    \ Flight 6
                           <--------             Finished    /

Handshake Message Format

   struct {
     HandshakeType msg_type;
     uint24 length;
     uint16 message_seq;                               // New field
     uint24 fragment_offset;                           // New field
     uint24 fragment_length;                           // New field
     select (HandshakeType) {
       case hello_request: HelloRequest;
       case client_hello:  ClientHello;
       case hello_verify_request: HelloVerifyRequest;  // New type
       case server_hello:  ServerHello;
       case certificate:Certificate;
       case server_key_exchange: ServerKeyExchange;
       case certificate_request: CertificateRequest;
       case server_hello_done:ServerHelloDone;
       case certificate_verify:  CertificateVerify;
       case client_key_exchange: ClientKeyExchange;
       case finished: Finished;
     } body;
   } Handshake;

Handshake Message Type

   enum {
     hello_request(0), client_hello(1), server_hello(2),
     hello_verify_request(3),                          // New field
     certificate(11), server_key_exchange (12),
     certificate_request(13), server_hello_done(14),
     certificate_verify(15), client_key_exchange(16),
     finished(20), (255) } HandshakeType;

在 DTLS Handshake 中,通信的双方有 client 和 server 之分,因此在 Handshake Message Type 中定义了 client_hello、server_hello、server_key_exchange 、server_hello_done 和 client_key_exchange 共5个以 client/server 为前缀的枚举值。

Handshake Message

基于TLS,扩展了HelloVerifyRequest,TLS Handshake详见: RFC 5246
HelloRequest

      struct { } HelloRequest;

ClientHello

      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;

HelloVerifyRequest


ServerHello

      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;

Hello Extensions

      struct {
          ExtensionType extension_type;
          opaque extension_data<0..2^16-1>;
      } Extension;

      enum {
          signature_algorithms(13), (65535)
      } ExtensionType;

Certificate

      opaque ASN.1Cert<1..2^24-1>;

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

ServerKeyExchange

      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 {} ;
                 /* message is omitted for rsa, dh_dss, and dh_rsa */
              /* may be extended, e.g., for ECDH -- see [TLSECC] */
          };
      } ServerKeyExchange;

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;

ClientKeyExchange

      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;

EncryptedPreMasterSecret

     struct {
          ProtocolVersion client_version;
          opaque random[46];
      } PreMasterSecret;

      struct {
          public-key-encrypted PreMasterSecret pre_master_secret;
      } EncryptedPreMasterSecret;

ClientDiffieHellmanPublic

      enum { implicit, explicit } PublicValueEncoding;

      struct {
          select (PublicValueEncoding) {
              case implicit: struct { };
              case explicit: opaque dh_Yc<1..2^16-1>;
          } dh_public;
      } ClientDiffieHellmanPublic;

CertificateVerify

   Structure of this message:

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

Change Cipher Spec Message

      struct {
          enum { change_cipher_spec(1), (255) } type;
      } ChangeCipherSpec;

Finished

      struct {
          opaque verify_data[verify_data_length];
      } Finished;

      verify_data
         PRF(master_secret, finished_label, Hash(handshake_messages))
            [0..verify_data_length-1];

DTLS 超时重传机制

可以采用 DTLS_set_timer_cb 进行超时重传。
DTLS Record 支持 Message Seq,因此对端可以正确识别重传包(重传的Seq不变)。

DTLS in OpenSSL

SSL_CTX *SSL_CTX_new(const SSL_METHOD *method); 创建一个新的 SSL_CTX 对象作为 framework 来建立 TLS/SSL 或 DTLS 连接。

OpenSSL提供了DTLS_method, DTLS_server_method, DTLS_client_method, DTLSv1_method, DTLSv1_server_method, DTLSv1_client_method, DTLSv1_2_method, DTLSv1_2_server_method, DTLSv1_2_client_method用于创建DTLS的SSL_CTX 。

SSL *SSL_new(SSL_CTX *ctx);为 connection 创建 SSL 结构。

我们可以使用 OpenSSL 提供的 API 管理 CTX 和 SSL。
常用的有:

// set list of available SSL_CIPHERs
int SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str);

// load certificate 
 int SSL_CTX_use_certificate(SSL_CTX *ctx, X509 *x);

//  load key data
int SSL_CTX_use_PrivateKey(SSL_CTX *ctx, EVP_PKEY *pkey);

// set peer certificate verification parameters
void SSL_CTX_set_verify(SSL_CTX *ctx, int mode, SSL_verify_cb verify_callback);
// set peer certificate verification parameters 
// 深度?正如前文所述,证书存在依赖,类似树?
void SSL_CTX_set_verify_depth(SSL_CTX *ctx, int depth);

// manage whether to read as many input bytes as possible
SSL_CTX_set_read_ahead(SSL_CTX *ctx, int yes);

// Configure and query SRTP support
int SSL_CTX_set_tlsext_use_srtp(SSL_CTX *ctx, const char *profiles);

// Store and retrieve extra data from the SSL_CTX, SSL or SSL_SESSION
int SSL_set_ex_data(SSL *s, int idx, void *arg);

// handle information callback for SSL connections
void SSL_set_info_callback(SSL *ssl, void (*callback)());

// manipulate SSL options
long SSL_set_options(SSL *ssl, long options);

// perform a TLS/SSL handshake
int SSL_do_handshake(SSL *ssl);

// Set callback for controlling DTLS timer duration
void DTLS_set_timer_cb(SSL *s, DTLS_timer_cb cb);

OpenSSL对X509证书的支持:

// X509 certificate ASN1 allocation functions
X509 *X509_new(void);  // void X509_free(X509 *a);

// X509_NAME_new : ASN1 object utilities
// example : X509_NAME *X509_NAME_new(void);  
TYPE *TYPE_new(void);  // void TYPE_free(TYPE *a);

// X509_NAME modification functions
int X509_NAME_add_entry_by_txt(X509_NAME *name, const char *field, int type,
                                const unsigned char *bytes, int len, int loc, int set);

// get and set issuer names
int X509_set_issuer_name(X509 *x, X509_NAME *name);

// get and set subject names
int X509_set_subject_name(X509 *x, X509_NAME *name);

// get or set certificate, certificate request or CRL version
 int X509_set_version(X509 *x, long version);

// get or set certificate or certificate request public key
int X509_set_pubkey(X509 *x, EVP_PKEY *pkey);

// sign or verify certificate, certificate request or CRL signature
int X509_sign(X509 *x, EVP_PKEY *pkey, const EVP_MD *md);

// get digest of various objects
int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md,
                 unsigned int *len);

更多详见:
OpenSSL Man

0RTT Handshake in TLS1.3

在《密码学简述》一文中的对称密钥分配一节中提到一种方案:如果A和B各自有一个到达第三方C的加密链路,C能够在加密链路上传递密钥给A和B。
0RTT Handshake似乎便是源于这个想法,RFC8446在section-2.3写道:When clients and servers share a PSK (either obtained externally or via a previous handshake), TLS 1.3 allows clients to send data on the first flight ("early data"). The client uses the PSK to authenticate the server and to encrypt the early data.
我们可以将A和B视为clients and servers,将C视为PSK。

         Client                                               Server

         ClientHello
         + early_data
         + key_share*
         + psk_key_exchange_modes
         + pre_shared_key
         (Application Data*)     -------->
                                                         ServerHello
                                                    + pre_shared_key
                                                        + key_share*
                                               {EncryptedExtensions}
                                                       + early_data*
                                                          {Finished}
                                 <--------       [Application Data*]
         (EndOfEarlyData)
         {Finished}              -------->
         [Application Data]      <------->        [Application Data]

rfc8446#section-2.3

上一篇下一篇

猜你喜欢

热点阅读