下面是一个ssl握手的过程,没有进行客户端验证:
1.C-S:ClientHello---cipher-suit-list
2.S-C:ServerHello---selected-cipher-suit
3.S-C:ServerKeyExchange
4.S-C:ServerHelloDone
5.C-S:ClientKeyExchange
6.C-S:完成
7.S-C:完成
第3步是否发送要看c和s协商的cipher-suit是什么,cipher-suit包含四个部分(将摘要算法并入认证算法的话也可以看作三个部分),第一是密钥交换算法,第二是签名算法/验签算法,第三是摘要算法,第四是对称加密算法,RFC2246中建议了很多中组合,一般写法是"密钥交换算法-签名算法-对称加密算法-摘要算法",如果只有rfc的建议是可用的,那就难免要在各个ssl实现中加以若干硬性的规定,这样密钥交换和认证就不得不耦合起来了,比如使用ECC算法签名的证书不能使用RSA算法进行密钥交换,证书中密钥太长的的涉及出口限制的必须使用临时rsa进行密钥交换,如果使用rsa作为密钥交换算法,那么在ClientKeyExchange中的pre-master必须用证书中的公钥加密等等,之所以有这么多限制就是因为一些人或者机构的管理因素在里面,比如美国的出口限制等等,从协议本身来说,这些限制是不应该的,证书仅仅用于认证,而不和密钥交换挂钩,当然,它们之间也不是没有任何关系,比如KeyExchange消息本身就需要认证,而认证的公私钥信息可以在证书中。
协议本身来看,任何的算法都能组合成一个cipher-suit,以RFC2246的一个建议为例,使用RSA作为密钥交换算法的不能发送ServerKeyExchange消息,我们来看一下如何违反它从而实现一个新的不在RFC中的cipher-suit,这个cipher-suit使用rsa作为密钥交换算法,但是使用ecdsa作为认证算法,暂且不考虑对称加密算法和摘要算法。仍以上述握手过程为例,第2步时server端选择了RSA-ECDSA-XX-YY这个cipher-suit,紧接着第3步,server将自己的使用ecdsa签名的证书发送给了client,client用ca的ecc公钥验证server证书中ecc签名,然后server违反rfc建议,在密钥交换算法是rsa的情况下发送ServerKeyExchange消息,由于使用rsa进行密钥交换,而证书中的公钥是ecc算法签名的,那么这个ServerKeyExchange消息中必须包含一个临时的rsa公钥,server自己保留临时rsa私钥,然后server用自己的ecc私钥将这个ServerKeyExchange消息进行签名后发给client,client收到后会使用server证书中的ecc公钥来验证这个签名,通过后保存该消息中提取的server的临时rsa公钥,接着处理完hellodone消息后生成一个pre-master,然后用刚才保存的server临时rsa公钥加密这个pre-master作为ClientKeyExchange消息发送给server,随后两端使用密钥导出算法导出一个对称密钥,认证完成,密钥交换完成,握手完成。
1.C-S:ClientHello---cipher-suit-list
2.S-C:ServerHello---selected-cipher-suit
3.S-C:ServerKeyExchange
4.S-C:ServerHelloDone
5.C-S:ClientKeyExchange
6.C-S:完成
7.S-C:完成
第3步是否发送要看c和s协商的cipher-suit是什么,cipher-suit包含四个部分(将摘要算法并入认证算法的话也可以看作三个部分),第一是密钥交换算法,第二是签名算法/验签算法,第三是摘要算法,第四是对称加密算法,RFC2246中建议了很多中组合,一般写法是"密钥交换算法-签名算法-对称加密算法-摘要算法",如果只有rfc的建议是可用的,那就难免要在各个ssl实现中加以若干硬性的规定,这样密钥交换和认证就不得不耦合起来了,比如使用ECC算法签名的证书不能使用RSA算法进行密钥交换,证书中密钥太长的的涉及出口限制的必须使用临时rsa进行密钥交换,如果使用rsa作为密钥交换算法,那么在ClientKeyExchange中的pre-master必须用证书中的公钥加密等等,之所以有这么多限制就是因为一些人或者机构的管理因素在里面,比如美国的出口限制等等,从协议本身来说,这些限制是不应该的,证书仅仅用于认证,而不和密钥交换挂钩,当然,它们之间也不是没有任何关系,比如KeyExchange消息本身就需要认证,而认证的公私钥信息可以在证书中。
协议本身来看,任何的算法都能组合成一个cipher-suit,以RFC2246的一个建议为例,使用RSA作为密钥交换算法的不能发送ServerKeyExchange消息,我们来看一下如何违反它从而实现一个新的不在RFC中的cipher-suit,这个cipher-suit使用rsa作为密钥交换算法,但是使用ecdsa作为认证算法,暂且不考虑对称加密算法和摘要算法。仍以上述握手过程为例,第2步时server端选择了RSA-ECDSA-XX-YY这个cipher-suit,紧接着第3步,server将自己的使用ecdsa签名的证书发送给了client,client用ca的ecc公钥验证server证书中ecc签名,然后server违反rfc建议,在密钥交换算法是rsa的情况下发送ServerKeyExchange消息,由于使用rsa进行密钥交换,而证书中的公钥是ecc算法签名的,那么这个ServerKeyExchange消息中必须包含一个临时的rsa公钥,server自己保留临时rsa私钥,然后server用自己的ecc私钥将这个ServerKeyExchange消息进行签名后发给client,client收到后会使用server证书中的ecc公钥来验证这个签名,通过后保存该消息中提取的server的临时rsa公钥,接着处理完hellodone消息后生成一个pre-master,然后用刚才保存的server临时rsa公钥加密这个pre-master作为ClientKeyExchange消息发送给server,随后两端使用密钥导出算法导出一个对称密钥,认证完成,密钥交换完成,握手完成。
上述的整个过程理解起来很简单,就把ecc算法签名的证书当成密钥太长并有出口限制的rsa证书即可。总之,不考虑匿名dh以及一切类似情况下,任何需要验证的地方,公钥一般都取证书里面的,私钥都取本地加载的,涉及密钥交换的地方,严格按照cipher-suit中的算法进行。以上的论述在OpenSSL中不被支持,要想让OpenSSL支持这个RSA-ECDSA-XX-YY的话就必须修改OpenSSL的源代码,这个修改很简单,仅仅修改s3_srvr.c,s3_clnt.c等不多的几个文件即可,加上对诸如(l & SSL_kRSA) && (l & SSL_aECDSA)等组合的判断,本文不述。总之,就协议而言,任意的算法都能组合成一个cipher-suit。
本文转自 dog250 51CTO博客,原文链接:http://blog.51cto.com/dog250/1271782