2.6 更安全的传输方式——SSL
如果读者只是想开发个人使用的小网站,那么这一节的内容就显得有些无关紧要。然而对于企业网站,使用更加安全的数据传输是必要的,使用单纯的HTTP连接,所有的内容都以明文传输,这种方式是极不安全,就连通常被认为安全的“Post”操作,其安全性也无法保证。
因此我们才需要更安全的HTTPS(HTTP+SSL),下面的图片(如图2-4所示)描述了SSL在网络通信中的位置。
图2-4
2.6.1 什么是SSL
SSL(Secure Sockets Layer,安全套接层)协议及其继任者TLS(Transport Layer Security,传输层安全)协议是为网络通信提供安全及数据完整性的一种安全协议。TLS与SSL在传输层对网络连接进行加密。 SSL的一大优势在于它独立于上层协议,和HTTP结合即为HTTPS,和WebSocket结合即为WSS。
SSL协议是由网景公司于1994年推出,其目的是为网络通信提供可靠的加密方式,这一协议于1999年被IETF(Internet Engineering Task Force)标准化,标准名称为TLS。
通常认为SSL和TLS指代同一个标准,两者之间的差异极小。
2.6.2 SSL原理
不同的SSL握手过程存在差异,分为以下三种:
- 只验证服务器
- 验证服务器和客户端
- 恢复原有会话
我们在这里只介绍第一种,下面是其建立连接的过程。
(1)客户端发送Client Hello消息,该消息包括SSL版本信息、一个随机数(假设它是random1)、一个session id(用来避免后续请求的握手)和浏览器支持的密码套件(cipher suite)。
cipher suite的内容和它的含义一样,它是一个由加密算法名称组成的字符串,包括了以下4种用途的加密算法:
- 密钥交换算法:常用的有RSA、PSK等。
- 数据加密算法:常用的例如AES 256、RC4等。
- 报文认证信息码(MAC)算法:常用的例如MD5、SHA等。
- 伪随机数(PRF)算法。
例如下面这个字符串就是一个cipher suite:
其中各项的含义如下:
- ECDHE_RSA:密钥交换算法。
- AES_128_GCM:数据加密算法。
- SHA256:MAC算法。
伪随机数则是借助MAC算法实现的。
(2)服务器确定本次通信使用的SSL版本和其他信息,发送Server Hello给客户端,里面的内容包括服务器支持的SSL版本、一个伪随机数(random2)以及服务器的cipher suite等信息。
(3)服务器发送CA证书给客户端。
(4)服务器发送Server Hello done。
(5)客户端验证服务器证书的合法性后(Certificate Verify),利用证书中的公钥加密premaster secret(一个在对称加密密钥生成中的46字节的随机数字和消息认证代码)作为Client Key Exchange的消息发送给服务器。
(6)SSL客户端发送Change Cipher Spec消息,该消息属于SSL密码变化协议。
(7)客户端计算历史消息的hash值,然后使用服务器公钥加密后发送给服务器,服务器进行同样的操作,然后两个值结果相同表示密钥交换成功。
(8)服务器发送Change Cipher Spec消息。
(9)服务器计算历史消息的hash值,通过交换后的密钥加密,将其作为finished消息发送给客户端,客户端利用交换后的密钥解密,如果和本地历史消息相同就证明服务器身份。握手结束。
密钥交换的步骤
不管加密数据使用的是对称亦或是非对称算法,客户端和服务器都需要交换密钥,在对称加密的情况下,客户端需要将解密的密钥发送给服务器;非对称加密的情况下,则是要把自己的私钥发送给对方。
密钥交换有很多不同的算法,比较常见的是RSA算法,它是一种非对称式加密算法。
一个密钥交换通常分为Certificate Verify以及Client Key Exchange两个步骤,我们这里以RSA算法为例来讲述这两个步骤。
(1)Certificate Verify
客户端收到服务端传来的证书后,先验证该证书的合法性,验证通过后取出证书中的服务端公钥,再生成一个随机数Random3,再用服务端公钥加密Random3生成PreMaster Key。
(2)Client Key Exchange
上面客户端根据服务器传来的公钥生成了PreMaster Key,Client Key Exchange就将这个Key传给服务端,服务端再用自己的私钥解出这个PreMaster Key,得到客户端生成的Random3。再加上前面生成的Random1和Random2,至此,客户端和服务端都拥有Random1+ Random2 + Random3。
两边再根据同样的算法就可以生成一份密钥,握手结束后的应用层数据都是使用这个密钥进行对称加密。
使用三个随机数的原因是因为使用多个随机数来生成密钥不容易被暴力破解出来。
2.6.3 对称加密与非对称加密
对称密钥加密,又称私钥加密或会话密钥加密算法,即信息的发送方和接收方使用同一个密钥去加密和解密数据。它的最大优势是加/解密速度快,适合于对大数据量进行加密,但密钥管理困难。
非对称密钥加密系统,又称公钥密钥加密。它需要使用不同的密钥来分别完成加密和解密操作,一个公开发布,即公开密钥,另一个由用户自己保存,即私用密钥。信息发送者用公开密钥去加密,而信息接收者则用私用密钥去解密。公钥机制灵活,但加密和解密速度却比对称密钥加密慢得多。
2.6.4 关于CA
假设两个同学在课堂上传纸条,由于纸条的传递要经过好几个同学,他们不希望纸条的内容被其他同学知晓,于是他们打算采用非对称加密的方法,他们互相定义了一种加密和解密的方法,各自的加密内容只有自己的解密密码(私钥)才能解开。那么在传输信息之前,双方需要交换自己的加密方法(公钥)。
然而在第一次交换加密方法的纸条传递时,中间一名负责传递的同学看穿了他们的套路,把双方交换的公钥都换成了自己伪造的公钥,那么就可以轻松地使用自己的私钥读取他们之间的通信内容,这种做法就属于中间人攻击。
CA(Certification Authority,证书授权),通常表示一个第三方组织,专门用来验证服务器证书的准确性的。打个比方,也就是在上面交换公钥的时候,如果传纸条的双方约定好,要另一个他们都信得过的人(例如班主任)来验证双方的公钥无误,那么就可以放心地传纸条了。
一个CA文件包含的内容包括用户信息、CA签发机构信息、用户公钥、有效日期、CA签发机构签名(CA签发机构用私钥签名,用于将用户信息+用户公钥等信息进行签名确保内容的真实性)、CA签发机构的公钥(用于让用户验证签发证书是否是CA签发机构签发的)
CA证书需要CA机构来颁发,通常申请这么一个证书往往要花不少时间和精力,那么一些小企业通常会自己担任CA机构,即自己给自己网站的公钥签名,这是一种既当裁判又当运动员的方法,也是我们接下来的做法。
2.6.5 创建HTTPS服务
HTTPS即HTTP + SSL,目前国内的主流网站都在进行或者已经完成了HTTPS升级。
在使用前,我们需要创建公钥、私钥以及证书,这一切都可以通过openSSL这一工具来完成。Mac OSX自带了OpenSSL,在Windows和一些Linux发行版上需要自行下载安装。
为了得到签名证书,服务器需要先生成一个后缀为CSR(Certificate Signing Request)的文件。
下面的命令展示了服务器创建公钥、私钥以及证书的流程:
客户端的创建同理。
值得一提的是,在创建CSR文件的过程中,OpenSSL会提示用户输入一些配置信息,唯一需要注意的是common Name选项,如果开发者是在本地工作,那么就直接输入localhost即可,其他的选项都可以留空。
下面是一个配置的例子,如图2-5所示。
图2-5
创建好公钥和私钥之后,就可以开始创建使用SSL加密的服务器了。
代码2.18 创建HTTPS服务器
打开浏览器访问https://locahost:3001,注意一定要是HTTPS,因为我们只启动了HTTPS服务器,如果读者此时在使用最新的Chrome浏览器,那么浏览器会首先展示一个警告页面。如图2-6所示。
图2-6
如果我们选择继续访问,仍然能正常地看到服务器的返回信息,区别是在地址栏的最左边出现不安全的提醒,如图2-7所示。
图2-7
这是我们的证书没有经过正规的CA机构颁发的原因。
此外,服务器的控制台会打印unauthorized。
如果使用request方法请求这个服务器,同样要带上客户端的私钥。
加载了客户端证书之后,服务器会打印出authorized。
如果开发者想要获得由第三方组织颁发的证书,那么可以考虑使用letsencrypt.org这一网站提供的免费服务,步骤十分简单,它是由ISRG(Internet Security Research Group,互联网安全研究小组)提供的服务,得到了国外很多知名IT公司和机构的支持,读者可自行探索。
HTTPS的缺点
HTTPS的缺点在于比普通的HTTP连接要慢,普通的HTTP只需要三次握手就能建立TCP连接,而HTTPS还要加上额外的SSL验证过程,在一定时间上拖慢了打开页面的速度,这也是为什么HTTPS在早期没有普及开来的原因。
随着带宽的增加,SSL带来的时间损失相对没那么大了,尤其是国内,为了加强安全性和避免运营商流量劫持,各大网站都开始了HTTPS的升级。