【2018-06-13】SSL/TLS及证书概述
[历史归档]本文原发布于 cstriker1407.info 个人博客内容为历史存档仅供参考。发布时间2018-06-13 标题SSL/TLS及证书概述分类编程 标签tlsSSL/TLS简单笔记SSL和TLS的关系HTTPS和TLS的关系LS握手过程ClientHelloServerHelloCertificateServerKeyExchange可选CertificateRequest可选ServerHelloDoneCertificate可选ClientKeyExchangeCertificateVerify可选Finished证书相关参考链接《 https://segmentfault.com/a/1190000009002353 》本篇以TLS 1.2作为参考只介绍原理不深入算法的细节SSL和TLS的关系SSL(Secure Sockets Layer)和TLS(Transport Layer Security)的关系就像windows XP和windows 7的关系升级后改了个名字而已。下面这张表格列出了它们的历史协议 创建时间 创建者 RFC 注释SSL1.0 n/a Netscape n/a 由于有很多安全问题所以网景公司没有将它公之于众SSL2.0 1995 Netscape n/a 这是第一个被公众所了解的SSL版本SSL3.0 1996 Netscape rfc6101 由于2.0还是被发现有很多安全问题Netscape于是设计了3.0并且IETF将它整理成RFC发布了出来TLS1.0 1999 IETF rfc2246 TLS 1.0基于SSL 3.0修改不大在某些场合也被称之为SSL 3.1改名主要是为了和Netscape撇清关系表示一个新时代的来临。类似于饭店换老板了然后改了个名字厨师还是原来的TLS1.1 2006 IETF rfc4346TLS1.2 2008 IETF rfc5246TLS1.3 TBD IETF TBD 还在开发过程中draft最初的SSL只支持TCP不过现在已经可以支持UDP了请参考Datagram Transport Layer Security Version 1.2HTTPS和TLS的关系HTTPSHTTPTLS其它的协议也类似如FTPSFTPTLS。注意SSH和SSL/TLS是两个不同的协议SSH并不依赖于SSL/TLS加密相关的概念在正式开始介绍TLS之前先澄清一些跟加密相关的概念对称加密这是我们加密文件常用的方式加密的时候输入一个密码解密的时候也用这个密码加密和解密都用同一个密码所以叫对称加密。常见的算法有AES、3DES。非对称加密非对称加密是一个很神奇的东西它有两个不一样的密码一个叫私钥另一个叫公钥用其中一个加密的数据只能用另一个密码解开用自己的都解不了也就是说用公钥加密的数据只能由私钥解开反之亦然。私钥一般自己保存而公钥是公开的同等加密强度下非对称加密算法的速度比不上对称加密算法的速度所以非对称加密一般用于数字签名和密码对称加密算法的密码的交换。常见的算法有RSA、DSA、ECC。摘要算法摘要算法不是用来加密的其输出长度固定相当于计算数据的指纹主要用来做数据校验验证数据的完整性和正确性。常见的算法有CRC、MD5、SHA1、SHA256。数字签名数字签名就是“非对称加密摘要算法”其目的不是为了加密而是用来防止他人篡改数据。其核心思想是比如A要给B发送数据A先用摘要算法得到数据的指纹然后用A的私钥加密指纹加密后的指纹就是A的签名B收到数据和A的签名后也用同样的摘要算法计算指纹然后用A公开的公钥解密签名比较两个指纹如果相同说明数据没有被篡改确实是A发过来的数据。假设C想改A发给B的数据来欺骗B因为篡改数据后指纹会变要想跟A的签名里面的指纹一致就得改签名但由于没有A的私钥所以改不了如果C用自己的私钥生成一个新的签名B收到数据后用A的公钥根本就解不开。LS握手过程TLS主要包含两部分协议一部分是Record Protocol描述了数据的格式另一部分是Handshaking Protocols描述了握手过程本篇中只介绍握手过程不介绍具体的通信数据格式。握手的目的有两个一个是保证通信的双方都是自己期待的对方任何一方都不可能被冒充另一个是交换加密密码使得只有通信的双方知道这个密码而别人不知道。前一个就是我们常说的认证而后一个就是密码交换。认证是通过证书来达到的而密码交换是通过证书里面的非对称加密算法公私钥来实现的。先看握手的交互图±------- ±-------| | 1. ClientHello | || |-------------------------------------| || | | || | 2. ServerHello | || | 3. Certificate | || | 4. ServerKeyExchange (optional) | || | 5. CertificateRequest (optional) | || | 6. ServerHelloDone | || |------------------------------------ | || Client | | Server || | 7. Certificate (optional) | || | 8. ClientKeyExchange | || | 9. CertificateVerify (optional) | || | 10. Finished | || |------------------------------------ | || | | || | 11. Finished | || |------------------------------------ | |±------- ±-------注意 下面解释过程中用到的具体协议版本、算法和值都是示例实际中可能不是这些ClientHelloclient-server:hello咱建立个连接呗我这边的支持的最高版本是TLS1.1支持的密码套件cipher suite有“TLS_RSA_WITH_AES_128_CBC_SHA”和“TLS_RSA_WITH_AES_256_CBC_SHA256”支持的压缩算法有DEFLATE我这边生成的随机串是abc123456。这里有几点需要解释一下客户端会把自己最喜欢的密码套件放在最前面这样服务器端就会根据客户端的要求优先选择排在前面的算法套件密码套件就是一个密码算法三件套里面包含了一个非对称加密算法一个对称加密算法以及一个数据摘要算法。以TLS_RSA_WITH_AES_128_CBC_SHA为例RSA是非对称加密算法表示后面用到的证书里面的公钥用的是RSA算法通信的过程中需要签名的地方也用这个算法并且密码key的交换过程也使用这个算法AES_128_CBC是对称加密算法用来加密握手后传输的数据其密码由RSA负责协商生成SHA是数据摘要算法表示后面交换的证书里签名用到的摘要算法是sha1并且后续通信过程中需要用到数据校验的地方也是用的这个算法。在Record Protocol协议中摘要算法是必须的即数据包都需要有校验码而签名是可选的。ClientHello里面还可以包含session id即表示重用前面session里的一些内容比如已经协商好的算法套件等服务器收到session id后会去内存里面找如果这是一个合法的session id那么它就可以选择重用前面的session这样可以省去很多握手的过程。为了简化讨论这里不介绍session重用的问题。ServerHelloserver收到client的hello消息后就在自己加载的证书中去找一个和客户支持的算法套件相匹配的证书并且挑选一个自己也支持的对称加密算法证书里面只有非对称加密和摘要算法不包含对称加密算法。如果出现下面几种情况握手失败客户端支持的TLS版本太低比如server要求最低版本为1.2而客户端支持的最高版本是1.1根据客户端所支持的密码套件找不到相应要求的证书无法就支持的对称加密算法达成一致如果一切都OK那么服务器端将返回ServerHelloserver-client:hello没问题我们就使用TLS1.1吧算法采用“TLS_RSA_WITH_AES_256_CBC_SHA256”这个加密强度更高更安全压缩就算了我这边不支持我这边生成的随机数是654321def。如果server支持session重用的话这里还会返回session idCertificate服务器在发送完ServerHello之后紧接着发送Certificate消息里面包含自己的证书。当然这步在有些情况下可以忽略掉就是非对称加密算法选择使用dh_anon当然这是特殊的情况并且也不安全所以这里就不展开讨论。server-client: 这是我的证书身份证请过目ServerKeyExchange可选在前面的ServerHello中双方已经协商好了密码套件对于套件里面的非对称加密算法有些需要更多的信息才能生成一个可靠的密码而有些不需要比如RSA就不需要发送这个消息客户端自己生成一个准密码premaster就可以了而有些算法比如DHE_RSA就需要发送一点特殊的信息给客户端便于它生成premaster。premaster可以理解为最终密码的初级版本有了这个密码之后稍微再做一下计算就可以得到最终要使用的对称加密的密码server-client: 这是生成premaster所需要的一些信息请查收CertificateRequest可选只有在需要验证客户端的身份的时候才用得着在大部分情况下尤其是HTTPS这一步不需要。比如我们访问银行的网站我们只要保证那确实是银行的网站就可以了银行验证我们是通过账号密码而不是我们的证书。而U盾就是一个验证客户端的例子银行给你的U盾里面有你的证书你通过U盾访问银行的时候银行会验证U盾里面证书是不是你的这种情况下你和银行之间进行TLS握手的时候银行会给你发这个CertificateRequest请求。server-client: 把你的证书身份证也给我看看我要确认一下你是不是XXX。ServerHelloDoneserver-client: 我要告诉你的就是这么多了处理完了给我个回话吧。Certificate可选如果客户端在前面收到了服务器的CertificateRequest请求那么将会在这里给服务器发送自己的证书就算自己没有证书也要发送这个消息告诉服务器端自己没有证书然后由服务器端来决定是否继续。client-server: 这是我的证书身份证请过目ClientKeyExchange客户端验证完服务器端的证书后怎么验证证书将在后面介绍就会生成一个premaster生成的方式跟采用的密码交换算法有关以TLS_RSA_WITH_AES_128_CBC_SHA为例其密码交换算法是RSA于是客户端自己直接生成一个48字节长度的premaster即可不需要服务器发过来的ServerKeyExchange。client-server:这是计算真正密码要用到的premaster它是用你证书里的公钥加密了的哦记得用你的私钥解密后才能看到哦CertificateVerify可选如果客户端给服务器发了证书就需要发送该消息给服务器主要用于验证证书对应的私钥确实是在客户端手里。client-server:这是一段用我私钥加密的数据你用我给你的证书里的公钥解密看看如果能解开说明我没骗你私钥确实是在我手里并不是我随便找了一个别人的证书忽悠你发送的消息里面都带有校验码所以解密后计算下校验码能对上说明解密成功Finished当前面的过程都没问题后服务器和客户端都根据得到的信息计算对称加密用的密码这是RFC里面给出的计算方法master_secret PRF(pre_master_secret, “master secret”,ClientHello.random ServerHello.random)[0…47];虽然不太了解PRF的细节但至少客户端和服务器端用的算法和输入都是一样的所以得到的master密码也是一样的。这里pre_master_secret就是ClientKeyExchange里面客户端发给服务器端的premasterClientHello.random和ServerHello.random分别是握手开始时双方发送的hello请求中的随机字符串。这里加入随机数的原因主要是为了防止重放攻击保证每次握手后得到的密码都是不一样的然后双方将自己缓存的握手过程中的数据计算一个校验码并用对称加密算法和刚算出来的master密码加密发给对方这一步有两目的一个是保证双方算出来的master密码都是一样的即我这边加密的数据你那边能解开另一个目的是确保我们两个人的通信过程中的每一步都没有被其他人篡改因为握手的前半部分都是明文所以有可能被篡改只要双方根据各自缓存的握手过程的数据算出来的校验码是一样的说明中间没人篡改过。client-server: 这是用我们协商的对称加密算法和密码加密过的握手数据的指纹看能不能解开并且和你那边算出来的指纹是一样的server-client: 这是用我们协商的对称加密算法和密码加密过的握手数据的指纹你也看看能不能解开并且和你那边算出来的指纹是一样的如果双方发送完Finished而对方没有报错握手就完成了双发都得到了密码并且这个密码别人不知道后续的所有数据传输过程都会用这个密码进行加密加密算法就是ServerHello里面协商好的对称加密算法。证书相关开始之前看看我们常说的那些跟证书相关的概念基本概念私钥私钥就是一个算法名称加上密码串自己保存从不给任何人看公钥公钥也是一个算法名称加上密码串一般不会单独给别人而是嵌在证书里面一起给别人CA专门用自己的私钥给别人进行签名的单位或者机构申请签名文件在公钥的基础上加上一些申请人的属性信息比如我是谁来自哪里名字叫什么证书适用于什么场景等的信息然后带上进行的签名发给CA私下安全的方式发送带上自己签名的目的是为了防止别人篡改文件。证书文件证书由公钥加上描述信息然后经过私钥签名之后得到一般都是一个人的私钥给另一个人的公钥签名如果是自己的私钥给自己的公钥签名就叫自签名。签名过程CA收到申请文件后会走核实流程确保申请人确实是证书中描述的申请人防止别人冒充申请者申请证书核实通过后会用CA的私钥对申请文件进行签名签名后的证书包含申请者的基本信息CA的基本信息证书的使用年限申请人的公钥签名用到的摘要算法CA的签名。签完名之后证书就可以用了。证书找谁签名合适别人认不认你的证书要看上面签的是谁的名所以签名一定要找权威的人来签否则别人不认哪谁是权威的人呢那就是CA哪些CA是受人相信的呢那就要看软件的配置配置相信谁就相信谁比如浏览器里面默认配置的那些只要是那些CA签名的证书浏览器都会相信而你自己写的程序可以由你自己指定信任的CA。信任一个CA就是说你相信你手上拿到的CA的证书是正确的这是安全的前提CA的证书是怎么到你手里的这个不属于规范的范畴不管你是U盘拷贝的还是怎么弄来得反正你得确保拿到的CA证书没问题比如浏览器、操作系统等安装好了之后里面就内置了很多信任的CA的证书。那么CA的证书又是谁签的名呢一般CA都是分级的CA的证书都是由上一级的CA来签名而最上一级CA的证书是自签名证书。证书如何验证下面以浏览器为例说明证书的验证过程在TLS握手的过程中浏览器得到了网站的证书打开证书查看是哪个CA签名的这个证书在自己信任的CA库中找相应CA的证书用CA证书里面的公钥解密网站证书上的签名取出网站证书的校验码指纹然后用同样的算法比如sha256算出出网站证书的校验码如果校验码和签名中的校验码对的上说明这个证书是合法的且没被人篡改过读出里面的CN对于网站的证书里面一般包含的是域名检查里面的域名和自己访问网站的域名对不对的上对的上的话就说明这个证书确实是颁发给这个网站的到此为止检查通过如果浏览器发现证书有问题一般是证书里面的签名者不是浏览器认为值得信任的CA浏览器就会给出警告页面这时候需要谨慎有可能证书被掉包了。如访问12306网站由于12306的证书是自己签的名并且浏览器不认为12306是受信的CA所以就会给警告但是一旦你把12306的根证书安装到了你的浏览器中那么下次就不会警告了因为你配置了浏览器让它相信12306是一个受信的CA。

相关新闻

最新新闻

日新闻

周新闻

月新闻