Chinaunix首页 | 论坛 | 博客
  • 博客访问: 807772
  • 博文数量: 142
  • 博客积分: 3505
  • 博客等级: 中校
  • 技术积分: 1501
  • 用 户 组: 普通用户
  • 注册时间: 2011-07-30 19:30
文章分类

全部博文(142)

文章存档

2012年(33)

2011年(109)

分类: C/C++

2011-09-29 12:07:32

RFC4346中的内容, 摘取了我认为比较重要的部分,做个备忘.
 
0. Variants
   Defined structures may have variants based on some knowledge that is
   available within the environment.  The selector must be an enumerated
   type that defines the possible variants the structure defines.  There
   must be a case arm for every element of the enumeration declared in
   the select.  The body of the variant structure may be given a label
   for reference.  The mechanism by which the variant is selected at
   runtime is not prescribed by the presentation language.
       struct {
           T1 f1;
           T2 f2;
           ....
           Tn fn;
           select (E) {
               case e1: Te1;
               case e2: Te2;
               ....
               case en: Ten;
           } [[fv]];
       } [[Tv]];
   For example:
       enum { apple, orange } VariantTag;
       struct {
           uint16 number;
           opaque string<0..10>; /* variable length */
       } V1;
       struct {
           uint32 number;
           opaque string[10];    /* fixed length */
       } V2;
       struct {
           select (VariantTag) { /* value of selector is implicit */
               case apple: V1;   /* VariantBody, tag = apple */
               case orange: V2;  /* VariantBody, tag = orange */
           } variant_body;       /* optional label on variant */
       } VariantRecord;
   Variant structures may be qualified (narrowed) by specifying a value
   for the selector prior to the type.  For example, an
       orange VariantRecord
   is a narrowed type of a VariantRecord containing a variant_body of
   type V2.
 
1. RECORD LAYER PROTOCOL:
       struct {
           uint8 major, minor;
       } ProtocolVersion;
       enum {
           change_cipher_spec(20), alert(21), handshake(22),
           application_data(23), (255)
       } ContentType;
       struct {
           ContentType type;
           ProtocolVersion version;
           uint16 length;
           opaque fragment[TLSPlaintext.length];
       } TLSPlaintext;
1.1 HANDSHAKE FLOW:
      Client                                               Server
      ClientHello                  -------->
                                                      ServerHello
                                                     Certificate*
                                               ServerKeyExchange*
                                              CertificateRequest*
                                   <--------      ServerHelloDone
      Certificate*
      ClientKeyExchange
      CertificateVerify*
      [ChangeCipherSpec]
      Finished                     -------->
                                               [ChangeCipherSpec]
                                   <--------             Finished
      Application Data             <------->     Application Data

1.2 HANDSHAKE PROTOCAL:
      enum {
          hello_request(0), client_hello(1), server_hello(2),
          certificate(11), server_key_exchange (12),
          certificate_request(13), server_hello_done(14),
          certificate_verify(15), client_key_exchange(16),
          finished(20), (255)
      } HandshakeType;
      struct {
          HandshakeType msg_type;    /* handshake type */
          uint24 length;             /* bytes in message */
          select (HandshakeType) {
              case hello_request:       HelloRequest;
              case client_hello:        ClientHello;
              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;
 
1.2.1 CLIENT_HELLO:
      struct {
         uint32 gmt_unix_time;
         opaque random_bytes[28];
      } Random;
      opaque SessionID<0..32>;
      uint8 CipherSuite[2];    /* Cryptographic suite selector [LENGTH+LIST]*/
      enum { null(0), (255) } CompressionMethod;

      struct {
          ProtocolVersion client_version;
          Random random;
          SessionID session_id;
          CipherSuite cipher_suites<2..2^16-1>; 
          CompressionMethod compression_methods<1..2^8-1>;
      } ClientHello;
   关于客户端的cipher_suites,重要:
   cipher_suites
      This is a list of the cryptographic options supported by the
      client, with the client's first preference first.  If the
      session_id field is not empty (implying a session resumption
      request) this vector MUST include at least the cipher_suite from
      that session.  Values are defined in Appendix A.5.
      Each CipherSuite defines a key exchange algorithm, a bulk encryption 
      algorithm (including secret key length), and a MAC algorithm. 

1.2.2 SERVER_HELLO:
       struct {
           ProtocolVersion server_version;
           Random random;
           SessionID session_id;
           CipherSuite cipher_suite;
           CompressionMethod compression_method;
       } ServerHello;
   关于session_id的说明, 涉及复用:
   session_id
      This is the identity of the session corresponding to this
      connection.  If the ClientHello.session_id was non-empty, the
      server will look in its session cache for a match.  If a match is
      found and the server is willing to establish the new connection
      using the specified session state, the server will respond with
      the same value as was supplied by the client.  This indicates a
      resumed session and dictates that the parties must proceed
      directly to the finished messages.  Otherwise this field will
      contain a different value identifying the new session.  The server
      may return an empty session_id to indicate that the session will
      not be cached and therefore cannot be resumed.  If a session is
      resumed, it must be resumed using the same cipher suite it was
      originally negotiated with.
   cipher_suite的说明:
   cipher_suite
      The single cipher suite selected by the server from the list in
      ClientHello.cipher_suites.  For resumed sessions, this field is
      the value from the state of the session being resumed.
1.2.3 Server Certificate:
   消息类型(需要查看x509v3的rfc: RFC3280):
      opaque ASN.1Cert<1..2^24-1>;
      struct {
          ASN.1Cert certificate_list<0..2^24-1>;
      } Certificate;
 
   关于服务端证书的一些说明:
   When this message will be sent:
      The server MUST send a certificate whenever the agreed-upon key
      exchange method is not an anonymous one.  This message will always
      immediately follow the server hello message.
   Meaning of this message:
      The certificate type MUST be appropriate for the selected cipher
      suite's key exchange algorithm, and is generally an X.509v3
      certificate.  It MUST contain a key that matches the key exchange
      method, as follows.  Unless otherwise specified, the signing
      algorithm for the certificate MUST be the same as the algorithm
      for the certificate key.  Unless otherwise specified, the public
      key MAY be of any length.
   密钥交换算法的证书密钥类型:
      Key Exchange Algorithm  Certificate Key Type
      RSA                     RSA public key; the certificate MUST
                              allow the key to be used for encryption.
      DHE_DSS                 DSS public key.
      DHE_RSA                 RSA public key that can be used for
                              signing.
      DH_DSS                  Diffie-Hellman key. The algorithm used
                              to sign the certificate MUST be DSS.
      DH_RSA                  Diffie-Hellman key. The algorithm used
                              to sign the certificate MUST be RSA.
   All certificate profiles and key and cryptographic formats are
   defined by the IETF PKIX working group [PKIX].  When a key usage
   extension is present, the digitalSignature bit MUST be set for the
   key to be eligible for signing, as described above, and the
   keyEncipherment bit MUST be present to allow encryption, as described
   above.  The keyAgreement bit must be set on Diffie-Hellman
   certificates.

   关于证书链的说明:
   Structure of this message:
      opaque ASN.1Cert<1..2^24-1>;
      struct {
          ASN.1Cert certificate_list<0..2^24-1>;
      } Certificate;
   certificate_list
      This is a sequence (chain) of X.509v3 certificates.  The sender's
      certificate must come first in the list.  Each following
      certificate must directly certify the one preceding it.  Because
      certificate validation requires that root keys be distributed
      independently, the self-signed certificate that specifies the root
      certificate authority may optionally be omitted from the chain,
      under the assumption that the remote end must already possess it
      in order to validate it in any case.
1.2.4 Server Key Exchange Message:
   这个需要看下DH交换和RSA交换的RFC,以便理解发送的参数:
   Structure of this message:
      enum { rsa, diffie_hellman } KeyExchangeAlgorithm;
      struct {
          opaque rsa_modulus<1..2^16-1>;
          opaque rsa_exponent<1..2^16-1>;
      } ServerRSAParams;
      rsa_modulus
          The modulus of the server's temporary RSA key.
      rsa_exponent
          The public exponent of the server's temporary RSA key.
      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 */
      dh_p
          The prime modulus used for the Diffie-Hellman operation.
      dh_g
          The generator used for the Diffie-Hellman operation.
      dh_Ys
        The server's Diffie-Hellman public value (g^X mod p).
      struct {
          select (KeyExchangeAlgorithm) {
              case diffie_hellman:
                  ServerDHParams params;
                  Signature signed_params;
              case rsa:
                  ServerRSAParams params;
                  Signature signed_params;
          };
      } ServerKeyExchange;
      struct {
          select (KeyExchangeAlgorithm) {
              case diffie_hellman:
                  ServerDHParams params;
              case rsa:
                  ServerRSAParams params;
          };
       } ServerParams;
      params
          The server's key exchange parameters.
      signed_params
          For non-anonymous key exchanges, a hash of the corresponding
          params value, with the signature appropriate to that hash
          applied.

      md5_hash
          MD5(ClientHello.random + ServerHello.random + ServerParams);
      sha_hash
          SHA(ClientHello.random + ServerHello.random + ServerParams);
      enum { anonymous, rsa, dsa } SignatureAlgorithm;

      struct {
          select (SignatureAlgorithm) {
              case anonymous: struct { };
              case rsa:
                  digitally-signed struct {
                      opaque md5_hash[16];
                      opaque sha_hash[20];
                  };
              case dsa:
                  digitally-signed struct {
                      opaque sha_hash[20];
                  };
              };
          };
      } Signature;
1.2.5 Certificate request:
   When this message will be sent:
      A non-anonymous server can optionally request a certificate from
      the client, if it is appropriate for the selected cipher suite.
      This message, if sent, will immediately follow the Server Key
      Exchange message (if it is sent; otherwise, the Server Certificate
      message).
   Structure of this message:
      enum {
          rsa_sign(1), dss_sign(2), rsa_fixed_dh(3), dss_fixed_dh(4),
       rsa_ephemeral_dh_RESERVED(5), dss_ephemeral_dh_RESERVED(6),
       fortezza_dms_RESERVED(20), (255)
      } ClientCertificateType;
      opaque DistinguishedName<1..2^16-1>;
      struct {
          ClientCertificateType certificate_types<1..2^8-1>;
          DistinguishedName certificate_authorities<0..2^16-1>;
      } CertificateRequest;
      certificate_types
         This field is a list of the types of certificates requested,
         sorted in order of the server's preference.
  Values from 0 (zero) through 63 decimal (0x3F) inclusive are
         reserved for IETF Standards Track protocols.
      certificate_authorities
         A list of the distinguished names of acceptable certificate
         authorities.  These distinguished names may specify a desired
         distinguished name for a root CA or for a subordinate CA; thus,
         this message can be used to describe both known roots and a
         desired authorization space.  If the certificate_authorities
         list is empty then the client MAY send any certificate of the
         appropriate ClientCertificateType, unless there is some
         external arrangement to the contrary.
   Note: It is a fatal handshake_failure alert for an anonymous server
         to request client authentication.

1.2.6 Server Hello Done
   服务端发送这个消息表示server hello阶段的结束. 服务端发送此消息后将会
   等待客户端的回应.此消息意味着服务端支持key exchange的消息发送完毕,
   客户端可以继续它自己的key exchange的阶段.收到服务端的这个消息,客户端
   SHOULD确认服务端提供了一个有效的证书(如果需要)并且检查server hello的
   参数是可接受的.
   
   Structure of this message:
      struct { } ServerHelloDone;
1.2.7 Client certificate
   When this message will be sent:
      这是客户端收到server_hello_done之后发送的第一个消息.客户端发送此消
      息只有服务端发送了certificate_request消息时. 如果无可用证书,客户端
      SHOULD发送一个不包含证书的证书消息.也就是length为0的certificate_list
      结构.如果服务端对于客户端验证时require的,那将会导致一个fatal 
      handshake failure alert.
   Note: When using a static Diffie-Hellman based key exchange method
      (DH_DSS or DH_RSA), if client authentication is requested, the
      Diffie-Hellman group and generator encoded in the client's
      certificate MUST match the server specified Diffie-Hellman
      parameters if the client's parameters are to be used for the key
      exchange.
1.2.8 Client Key Exchange Message:
   When this message will be sent:
      由客户端发送,且MUST紧跟client certificate message(如果发送),否则
      就作为收到server hello done之后的第一个消息.
   Meaning of this message:
      With this message, the premaster secret is set, either though
      direct transmission of the RSA-encrypted secret or by the
      transmission of Diffie-Hellman parameters that will allow each
      side to agree upon the same premaster secret.  When the key
      exchange method is DH_RSA or DH_DSS, client certification has been
      requested, and the client was able to respond with a certificate
      that contained a Diffie-Hellman public key whose parameters (group
      and generator) matched those specified by the server in its
      certificate, this message MUST not contain any data.
   Structure of this message:
      The choice of messages depends on which key exchange method has
      been selected.  See Section 1.2.4 for the KeyExchangeAlgorithm
      definition.
      struct {
          select (KeyExchangeAlgorithm) {
              case rsa: EncryptedPreMasterSecret;
              case diffie_hellman: ClientDiffieHellmanPublic;
          } exchange_keys;
      } ClientKeyExchange;
1.2.8.1 RSA Encrypted Premaster Secret Message
  Meaning of this message:
      If RSA is being used for key agreement and authentication, the
      client generates a 48-byte premaster secret, encrypts it using the
      public key from the server's certificate or the temporary RSA key
      provided in a server key exchange message, and sends the result in
      an encrypted premaster secret message.  This structure is a
      variant of the client key exchange message and is not a message in
      itself.
   Structure of this message:
      struct {
          ProtocolVersion client_version;
          opaque random[46];
      } PreMasterSecret;
      client_version The latest (newest) version supported by the
         client.  This is used to detect version roll-back attacks.
         Upon receiving the premaster secret, the server SHOULD check
         that this value matches the value transmitted by the client in
         the client hello message.
      random
          46 securely-generated random bytes.
      struct {
          public-key-encrypted PreMasterSecret pre_master_secret;
      } EncryptedPreMasterSecret;
      pre_master_secret
          This random value is generated by the client and is used to
          generate the master secret.
1.2.8.2 Client Diffie-Hellman Public Value
   Meaning of this message:
      This structure conveys the client's Diffie-Hellman public value
      (Yc) if it was not already included in the client's certificate.
      The encoding used for Yc is determined by the enumerated
      PublicValueEncoding.  这个是一个变体,不是消息本身.
   Structure of this message:
      enum { implicit, explicit } PublicValueEncoding;
      implicit
          If the client certificate already contains a suitable Diffie-
          Hellman key, then Yc is implicit and does not need to be sent
          again.  In this case, the client key exchange message will be
          sent, but it MUST be empty.
      explicit
          Yc needs to be sent.
      struct {
          select (PublicValueEncoding) {
              case implicit: struct { };
              case explicit: opaque dh_Yc<1..2^16-1>;
          } dh_public;
      } ClientDiffieHellmanPublic;
      dh_Yc
          The client's Diffie-Hellman public value (Yc).
1.2.9 Certificate verify
   When this message will be sent:
      This message is used to provide explicit verification of a client
      certificate.When
      sent, it MUST immediately follow the client key exchange message.
   Structure of this message:
      struct {
           Signature signature;
      } CertificateVerify;
      The Signature type is defined in 1.2.4.
      CertificateVerify.signature.md5_hash
          MD5(handshake_messages);
      CertificateVerify.signature.sha_hash
          SHA(handshake_messages);
   Here handshake_messages refers to all handshake messages sent or
   received starting at client hello up to but not including this
   message, including the type and length fields of the handshake
   messages.
1.2.10 Finished(密文的,抓包看不到的)
   When this message will be sent:
      A finished message is always sent immediately after a change
      cipher spec message to verify that the key exchange and
      authentication processes were successful.  It is essential that a
      change cipher spec message be received between the other handshake
      messages and the Finished message.(中间的change cipher spec是必要的)
   Meaning of this message:
      The finished message is the first protected with the just-
      negotiated algorithms, keys, and secrets.  Recipients of finished
      messages MUST verify that the contents are correct.  Once a side
      has sent its Finished message and received and validated the
      Finished message from its peer, it may begin to send and receive
      application data over the connection.
   Structure of this message:
      struct {
          opaque verify_data[12];
      } Finished;
      verify_data
          PRF(master_secret, finished_label, MD5(handshake_messages) +
          SHA-1(handshake_messages)) [0..11];
      finished_label
          For Finished messages sent by the client, the string "client
          finished".  For Finished messages sent by the server, the
          string "server finished".
      handshake_messages
          All of the data from all messages in this handshake (not
          including any HelloRequest messages) up to but not including
          this message.  This is only data visible at the handshake
          layer and does not include record layer headers.  This is the
          concatenation of all the Handshake structures, as defined in
          7.4, exchanged thus far.
2 Cryptographic Computations
   为了保护连接, TLS的记录层需要一组算法,主密钥,服务端和客户端随机数的
   详细说明. authentication, encryption, and MAC algorithms由服务端选择
   的cipher_suite决定,并在server hello消息中指明.压缩算法在hello消息中
   协商.所有上述这些都用作计算主密钥.
2.1. Computing the Master Secret
   For all key exchange methods, the same algorithm is used to convert
   the pre_master_secret into the master_secret.  The pre_master_secret
   should be deleted from memory once the master_secret has been
   computed.
       master_secret = PRF(pre_master_secret, "master secret",
                           ClientHello.random + ServerHello.random)
       [0..47];
   The master secret is always exactly 48 bytes in length.  The length
   of the premaster secret will vary depending on key exchange method.
 
2.1.1. RSA
   When RSA is used for server authentication and key exchange, a 48-
   byte pre_master_secret is generated by the client, encrypted under
   the server's public key, and sent to the server.  The server uses its
   private key to decrypt the pre_master_secret.  Both parties then
   convert the pre_master_secret into the master_secret, as specified
   above.
   RSA digital signatures are performed using PKCS #1 [PKCS1] block type
   1. RSA public key encryption is performed using PKCS #1 block type 2.
2.1.2. Diffie-Hellman
   A conventional Diffie-Hellman computation is performed.  The
   negotiated key (Z) is used as the pre_master_secret, and is converted
   into the master_secret, as specified above.  Leading bytes of Z that
   contain all zero bits are stripped before it is used as the
   pre_master_secret.
   Note: Diffie-Hellman parameters are specified by the server and may
         be either ephemeral or contained within the server's
         certificate.
 
 
阅读(4453) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~