https基本原理

本文会讲解https的基本原理,文章会稍稍有些啰嗦,可能更倾向于对https还不是很了解的小白用户。

密码学相关概念

作为安全协议的底层数学基础,理解几种密码学的概念是必不可少的。在涉及到https的相关密码学里面,只需要理解两种加密算法的外在表现即可。

  1. 指纹。有时也叫摘要,在技术上也叫哈希。一般是指的一个消息的哈希值,比如某个字符串或文件的md5或shasum摘要值。
  2. 签名。用非对称加密算法里的私钥对明文消息的摘要进行加密,最终这个加密结果就叫签名。所以签名等于”对摘要进行加密”
  3. 非对称加密。有个公钥和私钥形成一个钥匙对,公钥可以对信息进行加密,只有私钥才能解开;私钥也可以对信息进行编码,只有公钥才能打开。
  4. 对称加密。只有一个秘钥key,对信息进行加密之后,只有用这个key才能还原信息。

有些人也认为非对称加密中,公钥加密私钥解密才叫 加密,而私钥加密公钥解密这不应该叫 加密,而应该叫编码或者签名,因为公钥是公开的。我觉得这样理解也可以,只要能明白非对称加密的表现和内涵即可。

对称加密

这种加密方式是我们最容易理解的算法,如果A想写一封信给B,而又怕中间的投递人拆开信封看到内容,那么A和B可以约定一种自己能看懂的文字、图形,来达到防偷窥的目的。而实际上这个过程本质上就是信息编码和解码的过程,如果能让这个编码解码是基于一个秘钥key的,那么这个秘钥key就可以称为这次对称加密算法的加密秘钥 / 加密key

非对称加密

由于对称加密会涉及到一个难以解决的问题,那就是 加密的秘钥如何保证安全送达. 所以数学家设计了一种算法,可以基于两个配对的秘钥对信息进行加解密。公钥对信息加密后只有配对的私钥能解开,同理私钥加密的数据只有公钥能解开。这个神奇的算法就解决了安全秘钥(第一点中提到的 加密key )如何安全传递的问题

虽然非对称加密很安全很强大,但是它也有缺点: “相对于对称加密它计算量更大,计算时间更长”。所以在大规模数据的安全通信场景中,普遍采用非对称加密技术来交换对称加密密钥,之后的通信都采用对称加密技术加密。

信息安全中的防泄密、防篡改

  1. 防泄密。防止明文信息在传输过程中被人偷窥、截获、嗅探
  2. 防篡改和防冒充。这里主要利用刚刚说到的签名技术(签名技术的实现是依赖非对称加密技术)

下面看下防泄密和防篡改两个目标,加密技术是如何通过算法机制来实现的:

  • 防泄密: 非对称加密在实现 消息保密 时公钥负责加密,私钥负责解密,因为别人解不开啊,自然就实现了防偷窥。你要问了,既然对称加密可以简单的使用一个加密key来实现防泄密,为何要用更复杂的非对称加密呢? 原因很简单: 这里有一个小细节,因为 对称加密 要实现防泄密的前提是双方需要提前约定好秘钥key,在双方没有约定的情况下,如何安全的进行明文加密传输呢,这时非对称加密就可以解决咯。(在SSH和https中建立会话通道的时候就是利用这个机制来实现的,即公钥加密来协商对称加密的密钥)

  • 防篡改/防伪造和防冒充:非对称加密技术的 签名 手段可以实现不让中间篡改你的消息,且能确认发送者的身份。

    签名技术确实很强大!签了名的消息如果被篡改是能感知到的。数字签名的原理是: 私钥加密公钥解密。即: A方把明文计算出摘要,再用A的私钥对摘要进行加密得到签名(私钥加密保证了摘要不可能被改变)。 然后签名和明文一起发给B方。 B方用公钥解开签名得到摘要, 跟明文的摘要做对比。

    在无人可以获取到A方私钥的情况下,如果有中间人篡改了明文,他也无法给他签一个基于 此次会话的公私钥对 的正确的签名(因为他没有合法的私钥),这会被接受者校验时识破。 同样,如果有中间人来自己伪造消息,他也无法生成一个跟接受者能合法校验的签名。

    所以签名技术可以实现防篡改/防伪造、防冒充。其实 防篡改防伪造防冒充本质上指的是一个意思,毕竟冒充的目的也是为了给接收者发送一个伪造的消息。所以总结来看:

    通过签名技术我可以校验一个消息的真实性(这个真实性表现在确保了一定是我期待的那个人发给我的消息—即一定是持有我的公钥所对应的私钥的那个人发给我的消息,而不是被中间人或其他人投放过来的消息。 当然这里的前提是我手上拿着的公钥必须是对的,这个接受者手上的公钥的正确性要靠后文讲到的证书机制来保证一定是会话另一方的).

协议: SSL/TLS/Telnet/SSH

要理解http和https,我觉得也有必要去理解 SSL/TLS/Telnet/SSH 这几种协议的区别和联系,大家可以去网络上搜集更详细的资料。我在这里会简单解答这个问题。

首先要知道的是: 他们都是在TCP网络传输层之上的 应用层协议:

  • Telnet是一种远程登录的协议,默认使用23端口,可以实现对远程主机发送信息或命令。通俗来讲,telnet可以用于登录并管理远程服务器,但telnet的设计是不安全的,它并不使用任何安全机制,通过网络/互联网传输明文格式的数据,包括密码。所以谁都能嗅探数据包,获得这个重要信息。这就是为什么telnet不再用于通过公共网络访问网络设备和服务器的原因

  • SSH是一种安全的shell,默认使用22端口,通俗来讲他也是用来登录并管理远程服务器的一种协议,但他解决了登录时传递的密码安全问题,而且SSH传输是会压缩的,所以效率也比较高.

  • SSL/TLS它是通讯链路的附加层,应该说它只是提供一些加密的基础设施和基本操作(例如证书机制和秘钥交换机制)。好多协议都是基于SSL/TLS实现的—https, ftps。实际上这个SSL/TLS是对上层http报文进行包装和解析,从而实现本来明文的http报文被加密传输。

SSL提供了握手和加密手段,不是一个独立的应用层协议,可以基于它修改现有的应用使之安全,而SSH是基于SSL之上的应用层协议,跟一般的通过SSL加密的应用层协议只是简单的修改socket接口替换为ssl接口的机制不同,SSH是一个完全替换telnet和ftp的应用,并且可以基于之上使用端口转发功能为其他应用层提供安全通道

https如何建立连接

对于传统的http连接来说,其模型很简单,只需要三次握手建立TCP连接后,客户端和服务端就可以开始进行http报文的发送和响应了。而https同样是基于TCP,只是在http报文和TCP之间又加了一层握手,这个握手用于校验服务端传来的公钥的合法性(证书校验)并建立加密通道,其底层实现是基于SSL/TSL协议。

SSL协议的握手步骤是这样的:

第一步,浏览器给出协议版本号、一个浏览器客户端生成的随机数(Client random),以及客户端支持的加密方法,如RSA。

第二步,服务器收到握手请求后,确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数(Server random)。

第三步,浏览器确认数字证书有效(验证过程我们在后文第二部分讲解),然后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给服务器。

第四步,服务器使用自己的私钥,获取浏览器发来的随机数(即Premaster secret)。

第五步,服务器和浏览器此时应该都拥有了整个握手过程中出现的3个随机数,他们会各自根据约定的加密方法,使用前面的三个随机数,生成”对话密钥”(session key),用来加密接下来的整个对话过程。

所以一个https请求的过程中,握手阶段包含了 TCP协议的握手SSL协议的握手 的时间,总体上我通过工具测试大概SSL握手是TCP握手的三倍,而且证书的秘钥越长加解密时间则越多。 我们也能看出来,SSL协议应该属于一个应用层协议。

加密技术在https握手过程中的应用解析

一般在传输特别重要的信息(比如对称加密的秘钥)时,”消息内容保密”和”发送者的防冒充”是都要保证的,技术上的保障手段就是加密(消息保密)和签名(签名)。而HTTPS的连接过程就是对 消息内容保密保证消息防冒充防篡改 的典型应用。

  1. 签名来保证正确的服务器公钥传给浏览器。在浏览器获取公钥时,必须确保公钥一定是当前访问的网站发出的,且是完整的、正确的、未被篡改的。此时就用到了数字签名技术。 首先浏览器里默认自带系统里就拥有一个全球CA机构合法的公钥A。由于https网站都会去CA机构申请证书,这个证书是CA机构用私钥a签名过的证书(签名的内容是网站的公钥B、域名test.com、有效期等信息),所以利用这个操作系统里的CA公钥公钥A就能鉴别这个证书合法性,保证证书一定是CA机构颁发的,且没有被篡改。 然后读取证书里的明文内容,确定了跟当前访问的域名是一致。

  2. 公钥加密技术 来保证对称会话密钥的加密传输。当浏览器获取到了真实服务器的公钥之后,https在协商对称 密钥C 时候,要保证 密钥C 在传输过程中不能被偷窥,所以这里使用了 公钥B 加密、服务器收到后用 私钥b 解密,保证了这个 密钥C 的防偷窥加密传输。

最终浏览器通过一系列的签名验证手段,验证了如下内容:

  1. 证书及其内部的公钥确实肯定不是别人的,肯定是CA机构颁发的,证书的明文是合法的、完整的;另外CA机构颁发时肯定是校验了域名所有权的,所以证书的明文是合法的、完整的也就意味着证书里记录的域名一定是跟证书里的公钥是完全匹配的; 这也就意味着这个证书必须应用给里面记录的那个域名上,浏览器如果发现当前访问的网站域名根证书里的记录不匹配,会报出如下错误:
    httperror

  2. 浏览器通过公钥加密的手段把保密的待协商随机数发送给了拥有证书里公钥的配对私钥的那个人,也只有那个人(该公钥真正的网站主服务器)能解出真正的随机数。(所以哪怕有中间人在中间投放这个合法的CA证书骗过浏览器的证书校验,只要他没有私钥,也会在协商密钥阶段爆出SSL握手协商密钥错误)

最终的最终,两边各自都能推算出一个对称加密的秘钥key,且这个key是没有被任何中间人发现的。然后就可以使用对称加密进行信息加密传输了;因为对称加密速度比较快嘛。 此时对称加密的key可以确保是绝对安全的,因为SSL握手过程已经保障了这个key生成机制的安全。

这个过程跟SSH协议建立通道的过程还是很像的,除了SSH协议没有使用证书校验公钥合法性。

附录: 浏览器端验证证书合法性的步骤

一个完整的证书是CA机构颁发给网站主的,然后网站被访问时,服务器会将证书发送给浏览器。发送给浏览器的证书需要包含三部分内容:

  1. Certificate证书明文,里面包括了很多信息。比如网站域名,发证机关,有效期等;当然最重要的是网站主服务器的公钥会放在里面
  2. Certificate Signature Algorithm 证书加密算法。这是指的CA机构颁发证书时使用的非对称加密算法名称
  3. Certificate Signature Value 证书签名。这是CA机构给证书明文(包括了上面说的域名、发证机关等)进行哈希 然后用私钥加密后得到的非对称加密结果

以上这些内容(域名、公钥等),在你向CA机构给自己的域名申请证书时,都是需要提供的;而且要证明自己拥有域名的所有权(lets encrypt是通过提交一个域名操作的API token来证明的)。 一般申请https证书时你会在服务器上运行一个程序产生私钥、公钥,然后程序会把公钥、域名信息等提交给CA机构,CA机构给你签名后颁发证书给你。

SSL握手过程中浏览器是这样验证证书的:

  1. 该公钥证书的subject name(主题名–其实是域名)和所访问的服务器站点的名称是否一致;
  2. 该公钥证书的是否过期;
  3. 该公钥证书及其签发者证书链中的证书的数字签名是否有效(层层验证,一直验证到根CA证书为止)。

我们可以看出,证书的验证过程是要跟当前访问的域名做比对的;所以不仅仅是验证证书文件本身的合法性,还包括了你访问的目标网址是否跟合法证书里的name匹配。这一点验证就可以防止后文我们所讲到的证书劫持。

其中第3步,使用的是密码学技术就是签名和签名验证。签名这个概念是用来解决认证问题的,即确保消息一定是谁谁谁发的(防冒充);对于证书来说就是确保这个证书一定是浏览器/操作系统所信任的CA机构签发的。

而签名又依赖摘要技术和非对称加密技术,即A发送一个消息给B,A先把消息明文使用摘要算法加密获得一个摘要,再用私钥对摘要进行加密,加密出来的东西就叫”签名”t,然后把明文和签名t发送给B;B就可以用公钥解开签名t,再对比明文的哈希是否一致。

在证书校验部分,本篇会从通俗易懂的简要概述下证书校验的步骤,而不会从概念和密码学的角度去讲解。如果需要详细了解https里面的具体加密过程,可以参考网络上09年的这篇讲解https文章: http://www.cnblogs.com/hyddd/archive/2009/01/07/1371292.html

验证证书是受信任的有何作用

证书是信任的CA机构颁发的,就能确保访问的网站是受信任的吗?
非也。证书校验只能代表这个含有公钥的证书确实是受信任的CA机构颁发的;而且证书里写的是当前访问的域名;由于浏览器认为,CA在颁发一个证书时,肯定是验证了当前域名所有者的,所以浏览器校验通过了证书,就意味着这个证书里的公钥就是证书了的域名的公钥,于是浏览器就亮起了“安全”的小绿灯。

当然,CA机构在接受申请时仅仅校验域名所有者就可以了吗? 其实申请证书的人还真的有可能就是个黑客呢(黑客窃取了域名变成域名所有者)?这样黑客用自己的服务器生成了私钥、公钥,再拿公钥去CA申请了一个合法证书;接下来黑客要做的就是通过DNS劫持等手段去让用户访问到自己服务器了,当然这种证书劫持的办法其实应该算是域名入侵了。 这就属于顶级安全事故了,一般公司的域名管理权限是不会被入侵的,这个概率是相当小了。 对于一些大公司来说,CA机构也会要求他们提供一些营业执照之类的,不会随随便便就颁发证书的。

CA机构是如何验证提供公钥的人确实是当前域名所有者的

CA在颁发证书时,一方面要交钱验证当前申请者的机构(也有不交钱的),另一种办法是他会看下当前域名是否是指向你发起公钥证书申请的服务器IP(因为域名所有者肯定不会把域名指向黑客服务器);还有其他一些办法,比如让你添加到自己域名上一个txt记录来验证,确保你确实有控制这个域名,那么就给你颁发证书。

lets crype免费域名证书,目前可以采用把你域名操作的 API Token提交给他的办法,证明你是域名的拥有者。

当然,对于更安全的场景,是需要提交企业营业执照的。这个说来话长,涉及到CA证书的级别和类型,如感兴趣可再深入去研究。

验证证书带来的性能开销

实际上整个证书验证的过程中,还可能因为一些原因导致耗时增加:

  1. 服务端发送的Server Certificate包可能包含上级证书链,在普遍使用2048位RSA的环境中,这个包会超过2K或者3K,在移动或慢速网络下可能会丢包并引起TCP的重传
  2. 浏览器会检查服务端证书的吊销状态—-根据服务端证书扩展项中的地址去下载黑名单或访问OCSP服务,如果这些地址无法访问或者被墙,则会让浏览器等上很长一段时间。 这可就蛋疼了,毕竟我们处在大中国,而浏览器都是舶来品
  3. 建立连接时的非对称加密算法本身非常耗时,这对CPU性能要求比较高。所以每次握手,对服务器来说都是一次压力的考验

怎么办呢? 我认为是没有办法的,为了安全我们必须做出这样的牺牲;当然这可以从http协议本身来减轻这个性能和速度开销的负担,比如http2.0就已经支持了多路复用的技术,目前的http1.1也支持keep-alive,这就大大减轻了多次创建连接带来的开销。

refer

RSA算法原理
数字签名是什么
两种典型SSL会话劫持技术小结
SSL/TLS协议运行机制的概述
图解SSL协议
https的七个误解
SSL的延迟有多大