OpenSSL 握手过程及重要操作
概述
大部分的网站都是支持SSL协议来保证数据在传输过程中的安全。因此了解OpenSSL握手过程及重要操作很重要。
使用RSA密钥交换算法时的标准SSL握手
主要步骤如下:
1. Client Hello
客户端发送给服务器端需要的信息。 这些信息包括客户端SSL版本号,cipher设置,会话特定数据。对应于上图中的步骤【1】.
2.Server Hello
服务器端发送给客户端的信息。这些信息包括客户端SSL版本号,cipher设置,会话特定数据。对应于上图中的步骤【2】.
3.认证和预主秘密(pre-master key)
客户端验证服务器证书。 (例如通用名称/日期/颁发者)客户端(取决于cipher)为会话创建预主密钥,使用服务器的公钥加密并将加密的预主密钥发送到服务器。对应于上图中的步骤【3】【4】.
4.生成主秘密(master -key)
服务器使用其私钥解密预主密钥(pre-master key)。 服务器和客户端都执行步骤以使用约定的cipher生成主密钥。对应于上图中的步骤【4】.
5.客户端与服务器端加密通信
客户端与服务器端使用步骤4生成的主密钥进行加密发送给对方的数据、解密接收到对方的数据。对应于上图中的步骤【9】.
SSL 握手过程中重要的操作
HMAC与PRF
TLS记录层使用密钥消息认证码(MAC)来保护消息的完整性。在RFC文档里和OpenSSL实现里使用的算法为HMAC,如[HMAC]RFC中所述,该结构基于散列函数。,如果需要的话,其他密码套件可以定义他们自己的MAC结构。
伪随机函数(PRF)将(secrets)秘密,(seed)种子和(identifying label)识别标签作为输入,并产生任意输出 长度。
数据扩展函数P_hash(secret,data),它使用一个散列函数将(secret)秘密和(seed)种子扩展为任意数量的输出:
P_hash(secret,seed)= HMAC_hash(secret,A(1)+ seed)+
HMAC_hash(秘密,A(2)+种子)+
HMAC_hash(秘密,A(3)+种子)+ ...
其中+表示串联。
A()被定义为:
A(0)=种子
A(i)= HMAC_hash(secret,A(i-1))
P_hash可以根据需要迭代多次以产生所需数量的数据。 例如,如果使用P_SHA256创建80个字节的数据,则必须迭代三次(通过A(3)),创建96个字节的输出数据; 最终迭代的最后16个字节将被丢弃,剩下80个字节的输出数据。
TLS的PRF是通过将P_hash应用于秘密而创建的:
PRF(秘密,标签,种子)= P_ <hash>(秘密,标签+种子)
该标签是一个ASCII字符串。 例如,标签“slithy toves”将通过散列以下字节来处理:73 6C 69 74 68 79 20 74 6F 76 65 73.
pre-master生成主密钥
如果将RSA用于密钥协商和身份验证,客户端将生成一个48字节的预主密钥,使用服务器证书中的公钥对其进行加密,并将结果发送给加密的预主密钥消息。 此结构是ClientKeyExchange消息的变体,本身不是消息。
客户端和服务器端使用相同的算法将pre_master_secret转换为master_secret。 一旦master_secret被计算出来,pre_master_secret应该从内存中被删除。
master_secret = PRF(pre_master_secret, "master secret",
ClientHello.random + ServerHello.random)
[0..47];
主密钥总是正好是48个字节。 预主密钥的长度取决于密钥交换方法。
RSA
当RSA用于服务器认证和密钥交换时,客户端会生成一个48字节的pre_master_secret,并在服务器的公钥下进行加密,然后发送到服务器。 服务器使用其私钥解密pre_master_secret。 双方然后将pre_master_secret转换为master_secret,如上所述。
Diffie-Hellman
传统的Diffie-Hellman计算被执行。 协商密钥(Z)被用作pre_master_secret,并被转换为master_secret,如上所述。 Z首字节的所有0在用作pre_master_secret之前被剥离。
注意:Diffie-Hellman参数由服务器指定,可能是临时的或包含在服务器的证书中。
ECC
ECC的添加仅对ClientHello,ServerHello,the server's Certificate
the client's Certificate message,ServerKeyExchange,ClientKeyExchange,CertificateRequest和CertificateVerify产生直接影响。
ECDH_ECDSA
在ECDH_ECDSA中,服务器的证书必须包含一个支持ECDH的公钥并且可以使用ECDSA进行签名。不得发送ServerKeyExchange(服务器证书包含客户端要求达到预主密钥所需的所有必要密钥信息)。客户端在与服务器的长期公钥相同的曲线上生成ECDH密钥对,并将其公钥发送到ClientKeyExchange消息中。
客户端和服务器都执行ECDH操作并使用生成的共享密钥作为预主密钥。
ECDHE_ECDSA
在ECDHE_ECDSA中,服务器的证书必须包含一个支持ECDSA的公钥并且可以使用ECDSA进行签名。
服务器在ServerKeyExchange消息中发送其临时ECDH公钥和相应曲线的规范。 这些参数必须使用与服务器证书中的公钥对应的私钥对ECDSA进行签名。
客户端在与服务器的短暂ECDH密钥相同的曲线上生成ECDH密钥对,并在ClientKeyExchange消息中发送其公钥。
ECDH_RSA
该密钥交换算法与ECDH_ECDSA相同,不同之处在于服务器的证书必须使用RSA而不是ECDSA进行签名。
ECDHE_RSA
此密钥交换算法与ECDHE_ECDSA相同,只是服务器的证书必须包含授权签名的RSA公钥,并且必须使用相应的RSA私钥计算ServerKeyExchange消息中的签名。 服务器证书务必用RSA签名。
参考资料
[1].https://wiki.openssl.org/index.php/SSL_and_TLS_Protocols
[2].https://tools.ietf.org/html/rfc5246
[3].https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_7.1.0/com.ibm.mq.doc/sy10660_.htm