国密TLS介绍

2021-07-27  本文已影响0人  yuan1028

握手协议总览

握手协议涉及以下过程

握手过程如下:

image-20210105142453782.png

如果客户端和服务端决定重用之前的会话,可不必重新协商安全参数。客户端发送客户端hello消息,并且带上要重用的会话标识。如果服务端游匹配的会话存在,服务端则使用相应的会话状态接受连接,发送一个具有相同会话标识的服务端hello消息。然后客户端和服务端各自发送密码规格变成消息和握手结束消息。至此握手过程结束,服务端和客户端可以开始数据安全传输。如果服务端没有匹配的会话标识,服务端会生成一个新的会话标识进行一个完整的握手过程。


image-20210105143953047.png

Hello消息

客户端Hello消息和服务端Hello消息用于确定双方的安全传输能力,包括协议版本,会话标识,密码套件等属性,并且产生和交换随机数。当新会话开始时,记录层连接状态中的密码算法,杂凑算法,压缩算法都初始化为空。

Client Hello
struct{
        ProtocolVersion client_version;
        Random random;
        SessionID session_id;
        CipherSuite cipher_suites<2..2^16-1>;
        CompressionMethod compression_methods<1..2^8-1>;
}
Server Hello

该消息为服务端Hello消息。

如果能从客户端Hello消息中找到匹配的密码套件,服务端发送这个消息作为对客户端Hello消息的回复。如果找不到匹配的密码套件,服务端将回应handshake failure报警消息。

struct{
        ProtocolVersion server_version;
        Random random;
        SessionID session_id;
        CipherSuite cipher_suite;
        CompressionMethod compression_method;
}ServerHello;

ServerCertificate消息

该消息为服务端证书消息。

服务端必须发送一个服务端证书消息给客户端,该消息总是紧跟在服务端Hello消息之后,当选中的密码套件使用RSA或ECC或ECDHE算法时,本消息的内容为服务端的签名证书和加密证书;当选中套件使用IBC或IBSDH算法时,本消息的内容为服务端标识和IBC公共参数,用于客户端与服务端协商IBC公开参数。

证书格式为X.509 v3,证书类型必须能适用于已经确定的密钥交换算法。密钥交换算法与证书密钥类型的关系如下。

密钥交换算法 证书密钥类型
RSA RSA密钥,必须使用加密证书中的公钥
IBC 服务端标识和IBC公共参数
IBSDH 服务端标识和IBC公共参数
ECC ECC公钥,必须使用加密证书中的公钥
ECDHE ECC公钥,必须使用加密证书中的公钥

证书消息结构如下

opaque ASN.1Cert<1..2^24-1>;
struct{
    ASN1.Cert cerificate;
}Certificate;

IBC标识及公共参数结构

opaque ASN.1IBCParam<1..2^24-1>;
struct{
      opaque ibc_id<1..2^16-1>;
      ASN.1IBCParam ibc_parameter;
}Certificate;

Server Key Exchange消息

本消息为服务端密钥交换消息。本消息传送的信息用于客户端计算产生48字节的预主密钥。服务端密钥交换消息结构定义如下:

enum{ECDHE,ECC,IBSDHE,IBC,RSA} KeyExchangeAlgorithm;
struct{
      select (KeyExchangeAlgorithm){
        case ECDHE:
               ServerECDHEParams params;
             digitally-signed struct{
                    opaque client_random[32];
                    opaque server_random[32];
                    ServerECDHEParams params;
             }signed_params;
        case ECC:
             digitally-signed struct{
                    opaque client_random[32];
                    opaque server_random[32]; 
                    opaque ASN.1Cert<1..2^24-1>;
             }signed_params;
        case IBSDH:
             ServerIBSDHParams params;
             digitally-signed struct{
                    opaque client_random[32];
                    opaque server_random[32];
                    ServerIBSDHParams params;
             }signed_params;
        case IBC:
                 ServerIBCParams params;
             digitally-signed struct{
                    opaque client_random[32];
                    opaque server_random[32];
                    ServerIBCParams params;
                    opaque IBCEncryptionKey[1024];
             }signed_params;
        case RSA:
             digitally-signed struct{
                    opaque client_random[32];
                    opaque server_random[32]; 
                    opaque ASN.1Cert<1..2^24-1>;
             }signed_params;
      }
}ServerKeyExchange;
struct {
      ECParameters curve_params;
      ECPoint public;
}ServerECDHParams;

Certificate Request 消息

本消息为证书请求消息。

如果服务端要求认证客户端,则应发送此消息,要求客户端发送自己的证书。

struct {
    ClientCertificateType certificate_types<1..2^8-1>;
    DistinguishedName certificate_authorities<0..2^16-1>;
}CertificateRequest

Server Hello Done消息

表示握手过程的Hello消息阶段完成。发送完该消息后服务端会等待客户端的响应消息。

客户端接收到服务端的hello完成消息之后,应验证服务端证书是否有效,并检验服务端的hello消息参数是否可以接受。如果可以接受,客户端继续握手过程。否则发送一个Handshake failure致命报警。

struct{}ServerHelloDone;

Client Certificate消息

本消息为客户端证书消息。如果服务端请求客户端证书,客户端要随后发送本消息。消息内容结构同服务端的certificate消息。

Client Key Exchange消息

本消息为客户端端密钥交换消息。

如果服务端请求客户端证书,本消息紧跟于客户端证书消息之后,否则本消息是客户端接受到服务端hello完成消息后所发送的第一条消息。

如果密钥交换算法使用RSA算法、ECC算法和IBC算法,本消息中包含预主密钥,该预主密钥由客户端产生,采用服务端的加密公钥进行加密。当服务端收到加密后的预主密钥后,利用相应的私钥进行解密,获取所述预主密钥的明文。如果是IBC算法,客户端利用获取的服务端标识和IBC公开参数,产生服务端公钥。如果是RSA算法,建议使用PKCS#1版本1.5对加密后的密文进行编码。如果密钥交换算法使用ECDHE算法或IBSDH算法,本消息中包含计算预主命钥的客户端密钥交换参数。

struct{
     select(KeyExchangeAlgorithm){
          case ECDHE:
               Opaque ClientECDHEParams<1..2^16-1>;
          case IBSDH:
               Opaque ClientIBSDHParams<1..2^16-1>;
          case ECC:
               Opaque ECCEncryptedPreMasterSecret<0..2^16-1>;
          case IBC:
               Opaque IBCEncryptedPreMasterSecret<0..2^16-1>;
          case RSA:
               Opaque RSAEncryptedPreMasterSecret<0..2^16-1>;
     }exchange_keys;
}ClientKeyExchange;

Certificate Verify消息

本消息为证书校验消息。

该消息用于鉴别客户端是否为证书的合法持有者,只有Client Certificate消息发送时才发送此消息,紧跟于客户端密钥交换消息之后。

证书校验消息的数据结构如下:

struct{
     Signature signature;
}CertificateVerify;

struct{
     select (SignatureAlgorithm){
          case rsa_sha1:
               digitally-signed struct{
                   opaque sha1_hash[20];
               };
          case rsa_sm3:
               digitally-signed struct{
                   opaque sm3_hash[32];
               };
          case ecc_sm3://当ECC为SM2算法时,也是用这个套件
                 digitally-signed struct{
                   opaque sm3_hash[32];
               };
          case ibs_sm3:
               digitally-signed struct{
                   opaque sm3_hash[32];
               };
     }
}Signature;

sm3_hash和sha1_hash是指hash运算的结果,运算的内容是自客户端Hello消息开始直到本消息为止(不包括本消息)的所有与握手有关的消息(加密证书要包在签名计算中),包括握手消息的类型和长度域。当使用SM2算法签名时,使用客户端的签名密钥,见GM/T0009和GM/T0010。

Finished消息

本消息为握手结束消息。

服务端和客户端各自在密码规格变更消息之后发送本消息,用于验证密钥交换过程是否成功,并校验握手过程的完整性。本消息用本次握手过程协商出的算法和密钥保护。本消息的接收方必须校验消息内容的正确性。一旦一方发送了握手结束消息,并且接收到了对方的握手结束消息并通过校验,就可以使用该连接进行数据安全传输。

握手结束消息数据结构如下:

struct{
      opaque verify_data[12];
}Finished

其中verify_data为校验数据,该数据产生方法如下:

PRF(master_secret,finished_label,SM3(handshake_messages))

密钥计算

预主密钥计算

ECDHE计算,ServerKeyExchange将ECDHEParams传递过来之后,client就可以计算生成preMasterSecret。server收到ClientKeyExchange也可以计算preMasterSecret.见ECDHE算法原理及实现。

主密钥计算

主密钥由48字节组成,由预主密钥、客户端随机数、服务端随机数、常量字符串,经PRF计算生成。`

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

// masterFromPreMasterSecret generates the master secret from the pre-master
// secret. See RFC 5246, Section 8.1.
func masterFromPreMasterSecret(version uint16, suite *cipherSuite, preMasterSecret, clientRandom, serverRandom []byte) []byte {
    seed := make([]byte, 0, len(clientRandom)+len(serverRandom))
    seed = append(seed, clientRandom...)
    seed = append(seed, serverRandom...)

    masterSecret := make([]byte, masterSecretLength)
    prfForVersion(version, suite)(masterSecret, preMasterSecret, masterSecretLabel, seed)
    return masterSecret
}

工作密钥

工作密钥包括校验密钥和加密密钥,具体密钥长度由选用的密码算法决定。由主密钥、客户端随机数、服务端随机数、常量字符串,经PRF计算生成。

计算方式如下:

key_block = PRF(SecurityParameters, master_secret, "key expanision", SecurityParameters.server_random, SecurityParameters.client_random)

直到生成所需长度的输出,然后按顺序分割得到所需的密钥:

client_write_MAC_secret[SecurityParameters.hash_size]

server_write_MAC_secret[SecurityParameters.hash_size]

client_write_key[SecurityParameters.key_material_length]

server_write_key[SecurityParameters.key_material_length]

// keysFromMasterSecret generates the connection keys from the master
// secret, given the lengths of the MAC key, cipher key and IV, as defined in
// RFC 2246, Section 6.3.
func keysFromMasterSecret(version uint16, suite *cipherSuite, masterSecret, clientRandom, serverRandom []byte, macLen, keyLen, ivLen int) (clientMAC, serverMAC, clientKey, serverKey, clientIV, serverIV []byte) {
    seed := make([]byte, 0, len(serverRandom)+len(clientRandom))
    seed = append(seed, serverRandom...)
    seed = append(seed, clientRandom...)

    n := 2*macLen + 2*keyLen + 2*ivLen
    keyMaterial := make([]byte, n)
    prfForVersion(version, suite)(keyMaterial, masterSecret, keyExpansionLabel, seed)
    clientMAC = keyMaterial[:macLen]
    keyMaterial = keyMaterial[macLen:]
    serverMAC = keyMaterial[:macLen]
    keyMaterial = keyMaterial[macLen:]
    clientKey = keyMaterial[:keyLen]
    keyMaterial = keyMaterial[keyLen:]
    serverKey = keyMaterial[:keyLen]
    keyMaterial = keyMaterial[keyLen:]
    clientIV = keyMaterial[:ivLen]
    keyMaterial = keyMaterial[ivLen:]
    serverIV = keyMaterial[:ivLen]
    return
}
上一篇下一篇

猜你喜欢

热点阅读