一文搞懂SSH、SSL和HTTPS

2,883 阅读15分钟

这是我参与8月更文挑战的第5天,活动详情查看:8月更文挑战(已经更文5天)

前言

打开自己的网页却显示的是另一个奇奇怪怪的页面?自己的网页中多了很多奇怪的弹窗?不知道小伙伴们有没有遇到过这类问题。想必大家都知道这是因为网页被劫持了,那么需要配证书,使用HTTPS,那么什么又是HTTPS呢?作为一个前端工程师,在日常工作中需要接触大量的网络请求,而弄明白一些网络相关的知识是必须的。今天就来介绍一下SSHSSLHTTPS

HTTP的缺陷

HTTP协议是运行在TCP之上的一个应用层的协议,它是web应用的基础。HTTP协议本质上是客户端发送请求到服务端,从服务端获取各种数据回来的一个过程。

image.png

HTTP协议是有缺陷的。因为它本身不具备加密功能,是明文运输各种数据的且不验证报文的完整性,在网络请求的过程中,会经过很多网络路由器转发你的请求,在每一个设备处都有可能会被窃听数据以及篡改数据。而且HTTP协议不验证通信双方的身份,有可能会遭遇伪装。

如果把HTTP协议的通信过程比作寄送快递的过程,A给B发一份快递,这份快递会经过很多快递员之手(网络路由器)。每个快递员都可以打开这个快递看里面到底有什么(明文运输),可以拿走或者放入一些奇怪的东西(不验证报文的完整性)。甚至可以拿另外的东西替换掉你原本的快递(不验证通信双方的身份,遭遇伪装)。

image.png

针对HTTP协议存在的缺陷,就出现了一些方案去解决。

  • 明文运输: 使用RSA算法进行非对称加密传输数据。
  • 报文完整性: 通过密钥生成数字签名,不公开密钥就能保证数据不被修改。
  • 验证双方身份: 通过数字证书来验证双方的身份。

对称加密

在一开始,用的是对称加密的方式,就是A使用密钥S进行加密,B收到信息后通过同一个密钥S进行解密。这样只有知道这个密钥S的人才能知道传输的信息是什么。

image.png

但是,这种方式存在一个很大的问题:A如何安全的把密钥S给到B呢?

答案是A发送给B密钥S走单独的安全信息通道(即没人能监听到该信道中的通信)。但这样会带来更多的问题:首先,有独立的安全信道,但是安全信道的带宽有限,不能直接用它发送原始消息。其次,A和B不能确定他们的密钥S可以保持多久而不泄露(即不被其他人知道)以及何时交换新的密钥S

非对称加密

为了解决对称加密存在的问题,数学家设计了一种非对称加密算法

非对称加密算法由一对公钥私钥组成。公钥私钥之间可以互相加解密,又因为加密和解密使用的是两个不用的密钥,所以这种算法也叫做非对称加密算法。用公钥加密的数据只能用对应的私钥解开,反之亦然。我们来看下非对称加密算法是如何解决A如何安全的把密钥S给到B的这个问题的。

我们把A当作客户端,把B当作服务端。A和B都生成一对密钥对,他们把各自的公钥都发布到网上,人人都能拿到公钥。这样,A就拿到了B的公钥B,B拿到了A的公钥A。当A想要发信息给B时,A拿B的公钥B加密信息,发送加密后的密文到B那里。因为拿公钥B加密的信息只有私钥B能解开,所以互联网链路上其他人拿到了这个信息也无法查看和更改。B拿到信息后再用私钥B解密,就能保证通信的安全了。

image.png

而如果是B向A发信息,反过来也一样,用A的公钥A加密信息,A收到信息后用私钥A解密信息。

那么问题又来了,你怎么知道公钥B就是B的呢?如果存在一个中间人两边冒充截取信息呢?

image.png

如上图所示,有个中间人M在客户端和服务端获取对方的公钥的时候,替换成了自己的公钥M,这样就能两边获取信息再篡改了。因为客户端和服务端无法验证这个公钥是否是来自对方的,如果被替换了也没办法认证。所以,就引入了一个数字证书的机制。

SSH

在了解数字证书之前,我们先思考一下,现在遇到的问题就是没法证明公钥是否是真的来自源目标的是吧?那么如果客户端A要向服务端B发送消息,客户端A生成了一对密钥对,如果是客户端A亲自把自己的公钥A放到服务器B上去,那么这个公钥A就一定能确定是来自于客户端A的。

熟悉吗?我们在使用github的时候,如果想上传代码,除了账号密码登录之外,是不是还有个SSH。我们一开始需要在自己的电脑上生成一对密钥对,然后把自己的公钥放在github上面,这样就能使用SSH去登录github了,然后就可以使用SSH去拉取或者推送代码了。

SSH,也就是Security Shell,由 IETF 的网络小组(Network Working Group)所制定,是目前较可靠,专为远程登录会话和其他网络服务提供安全性的协议。

SSH最初是UNIX系统上的一个程序,后来又迅速扩展到其他操作平台。SSH相当于一个隧道,数据通过的时候保护它不被泄露和篡改,为shell提供安全的传输和运用环境。具体来说,通过它可以安全的远程实行另一台UNIX体系上机器的指令。

注意:SSH只是一种用于主机用户登录,安全共享数据的网络应用程序。使用SSH后会在客户端和服务端建立一个安全通道,客户端就可以在这个通道中安全使用shell命令去操作服务端。

SSL

SSL不同于SSH,它是安全套接层(Secure Sockets Layer),是一种安全协议,是Netscape公司在推出Web浏览器首版时一起提出的。当浏览器访问以https://开头的URL时,浏览器通过SSL连接使用HTTP。SSL协议会在数据传输之前对数据进行加密再进行网络传输,保证了用户数据在传输链路上的安全。

SSL协议包含两个子协议:

  • 记录协议(SSL Record Protocol):说明SSL的数据包应该如何封装的。位于OSI七层模型的会话层上,为不同机器上的用户建立和管理会话。

  • 握手协议(SSL Handshake Protocol):说明通信双方如何协商共同决定使用什么算法以及算法使用的key。它在OSI七层模型会话层的下一层——表示层上,对他们之间的网络联接进行加密解密。

数字证书

那么问题又来了,我们日常访问页面,是从服务端拿数据的,服务端不可能像SSH给每个客户端都亲自发放一个公钥吧。所以又回到了最初的起点:因为客户端和服务端无法验证这个公钥是否是来自对方的,如果被替换了也没办法认证。 所以有了数字证书这个东西。

这里可以看看阮一峰老师的这篇文章数字证书

因为服务端的公钥无法在客户端证明确实是来自于服务端的,所以需要找一个第三方机构来做公证证明这个公钥确实是来自于服务端的。那怎么做公证呢?

服务端去证书授权中心申请证书,服务端会把自己的网站信息以及服务端公钥给到证书授权中心那边,而证书授权中心会根据这些生成一张由网站信息证书信息证书授权中心的数字签名以及服务端公钥等组成的证书。这里需要注意的是网站信息证书信息服务端公钥等信息在证书中都是以明文形式保存的,那么问题就来了,既然是明文那在互联网传输中肯定是不安全的,那么怎么证明这些东西没有被篡改过呢?这时候数字签名就派上用场了。

数字签名

数字签名是通过一些特定的hash算法计算得到的一串值。在上面我们有网站信息证书信息服务端公钥等明文信息,那我们就可以用特定的hash算法对这些信息进行计算得到一个hash值,这个hash值就是我们这个证书的指纹,它是唯一的标识。

当客户端获取到这张证书后,会用同样的hash算法对那些明文信息进行计算,这样就也能得到一个hash值,两个一对比,如果是相同的就可以证明这张证书是安全的,里面的信息没问题。但是,问题又来了,那么有个中间人截取了证书,并且修改明文信息后也生成一个hash值后替换原来的签名,那不是也不安全了吗? 所以,我们也需要对这个数字签名进行加密,用什么加密呢?用CA机构的私钥进行加密。那么用CA机构的私钥进行加密后,只有拥有CA机构的公钥才可以进行解密。而CA机构的公钥是预装在操作系统中的,就这解决了公钥的来源问题。就算存在一个第三方截取了这张证书并且拥有CA机构的公钥,它能解密并且篡改信息,但是因为没有CA机构的私钥无法进行加密,所以能保证此数字签名的安全。

ok,当客户端拿到了证书后,首先先验证这张证书是否来自于受信任的CA机构(是否受信任是事先放在计算机Cert Store里的,用户也可以手动添加),如果不是,就会抛出异常。如果是受信任的CA机构,那么则用此CA机构的公钥来解密证书授权中心的数字签名,获得一个hash值和对应的hash算法。客户端再使用hash算法进行计算,那么也获得了一个hash值,两两比对如果相同则可以证明此证书数据完整性。就可以直接拿服务端公钥来搞事情了。

数字证书:

image.png

HTTPS

HTTPS是Hypertext Transfer Protocol Secure,也称为 HTTP over TLS,HTTP over SSL,其实就客户端与服务系之间的HTTP通信基于TLS或则SSL协议。

简而言之:HTTPS = HTTP + SSL/TLS

当服务端通过数字证书来保证客户端确定能拿到真正的服务端公钥B后,我们就可以在SSL的基础上进行HTTP通信了,也就是HTTPS

在我的理解中,非对称加密中,私钥和公钥是 一对多 的关系。因为公钥是公开大量发放的,而私钥是唯一的,所以拥有公钥的一方可以确定拥有 私钥 一方的身份,而拥有私钥的一方无法确定拥有 公钥 一方的身份。所以,HTTPS就被分为单向认证和双向认证。

因为现在大部分使用的HTTPS传输的是页面,基本上是从服务端获取页面数据,所以客户端只需要确认服务端的唯一性即可,即客户端验证服务端的身份,确保页面没有被劫持被修改。像上面非对称加密中说到的中间人挟持的问题,通过数字证书解决了。

但是HTTPS只有非对称加密吗?

因为非对称加密需要对信息进行加解密,这其中是非常耗时的,对称加密算法比非对称加密算法快大约1500倍!所以,HTTPS在通过非对称加密进行身份验证完毕后,后续通信会通过对称加密来进行,我们来看看是怎么实现的。

HTTPS单向认证

我们先来看看HTTPS单向认证的流程:

image.png

  1. 客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。

  2. 服务端给客户端返回服务端申请的证书(包含服务端公钥B数字签名)、SSL协议版本号、加密算法种类、随机数等信息。

  3. 客户端拿到服务端返回的证书验证服务端的合法性,包括:

    • 证书是否过期
    • 该CA机构是否可靠
    • 返回的公钥是否能正确解开返回证书中的数字签名
    • 服务器证书上的域名是否和服务器的实际域名相匹配

    验证通过后,将继续进行通信,否则,终止通信

  4. 客户端向服务端发送自己所能支持的对称加密方案,供服务端进行选择。

  5. 服务端在客户端提供的加密方案中选择加密程度最高的加密方式。

  6. 服务端将选择好的加密方案通过明文方式返回给客户端。

  7. 客户端接收到服务端返回的加密方式后,使用该加密方式生成产生随机码,用作通信过程中对称加密密钥,使用服务端返回的公钥B进行加密,将加密后的随机码发送至服务端。

  8. 服务端收到客户端返回的加密信息后,使用自己的私钥B进行解密,获取对称加密密钥。 在接下来的会话中,服务端和客户端将会使用该对称加密密钥进行对称加密,保证通信过程中信息的安全。

HTTPS双向认证

除了HTTPS单向认证之外,还有HTTPS双向认证,因为在有些场景下需要服务端确认客户端的身份。那么,客户端也需要生成一个客户端证书发送给服务端来验证自己的身份。

HTTPS双向认证的流程:

image.png

  1. 客户端向服务端发送SSL协议版本号、加密算法种类、随机数等信息。

  2. 服务端给客户端返回服务端申请的证书(包含服务端公钥B数字签名)、SSL协议版本号、加密算法种类、随机数等信息。

  3. 客户端拿到服务端返回的证书验证服务端的合法性,包括:

    • 证书是否过期
    • 该CA机构是否可靠
    • 返回的公钥是否能正确解开返回证书中的数字签名
    • 服务器证书上的域名是否和服务器的实际域名相匹配

    验证通过后,将继续进行通信,否则,终止通信

  4. 服务端要求客户端发送客户端的证书,客户端会将自己的证书发送至服务端。

  5. 服务端验证客户端的证书,通过验证后,获得客户端公钥A

  6. 客户端向服务端发送自己所能支持的对称加密方案,供服务端进行选择。

  7. 服务端在客户端提供的加密方案中选择加密程度最高的加密方式。

  8. 服务端将选择好的加密方案通过客户端公钥A加密后返回给客户端。

  9. 客户端接收到服务端返回的信息后,通过客户端私钥A解密,获取到对称加密方式后,使用该加密方式生成产生随机码,用作通信过程中对称加密密钥,使用服务端返回的公钥B进行加密,将加密后的随机码发送至服务端。

  10. 服务端收到客户端返回的加密信息后,使用自己的私钥B进行解密,获取对称加密密钥。 在接下来的会话中,服务端和客户端将会使用该对称加密密钥进行对称加密,保证通信过程中信息的安全。

PS:使用单向认证还是双向认证是由服务端来决定的(默认单向)

结语

遇到网络劫持不要怕,HTTPS干死它。

如果看完这篇文章,对您有所帮助的话,还烦请您点个赞,点点关注,祝您生活愉快。