HTTPS
超文本传输安全协议(HyperText Transfer Protocol Secure,常称为HTTP over TLS、HTTP over SSL或HTTP Secure)是一种通过计算机网络进行安全通信的传输协议。HTTPS经由HTTP进行通信,但利用SSL/TLS来加密数据包。
为什么要用HTTPS
在网页上登录私人账号或者使用移动支付时,需要向服务端发送请求进行认证,通过请求头cookie或者token带上凭证,在服务端认证,然而在HTTP协议下,容易遭到中间人攻击,那通信就是在一个不安全信道内进行,也就不能保证交换数据的隐私与完整性。
所以,
HTTPS开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。
主要作用是在不安全的网络上创建一个安全信道,并可在使用适当的加密包和服务器证书可被验证且可被信任时,对窃听和中间人攻击提供合理的防护。
HTTPS为什么是安全的
HTTPS是如何保证在不安全的网络上信道安全?前面说过HTTPS是通过SSL/TSL加密数据包来实现HTTP的安全通信,所以问题的关键,SSL加密是怎么实现的?
公钥加密和对称性加密的组合
密钥是一种参数,它是在明文转换为密文或将密文转换为明文的算法中输入的参数。密钥分为对称密钥与非对称密钥。
为什么交换密钥?
客户端通过信道将消息发送给服务端,并对消息进行加密;接收方接收到消息,进行必要的解密,而这应该建立在接收者知道发送者如何加密的基础上;当服务端响应给客户端消息时,显然客户端应该知道服务端是如何加密的。
所以加密和解密应在密钥交换的基础上进行。
Symmetric Key Cryptography 对称密钥加密
即密钥加密。发送方和接收方共享密钥,加密和解密使用相同的密钥,或者两个简单相互推算的密钥。
- 发送方发送消息时,加密算法接受密钥和消息作为参数,对消息进行加密,加密完成后,生成密文,并通过信道发送给接收方。
- 接收方接收到消息后,解密算法使用同样的密钥将密文解密为明文。
- 如果有第三方恶意监听截获密文,没有密钥也很难解密。即使暴力破解,也要消耗巨大算力,这显然不划算。
在只有发送方和接收方知道密钥的情况下,才可以实现发送的密文可以被唯一解密。解密使用加密时的密钥,接收方和发送方使用同一密钥,这就是对称密钥加密。
所以,能否实现对称加密,就看能否保证密钥只被接收方和发送方访问。
如果通信是在一个不安全的信道内进行,如何保证?
Public-key cryptography 公钥加密
公钥密钥加密。它需要使用不同的密钥来分别完成加密和解密操作,一个公开发布,即公开密钥,另一个由用户自己秘密保存,即私用密钥。
- 发送方发送消息时,加密算法接受公钥和消息作为参数,加密完成后,密文通过不安全的信道发送给接收方。
- 接收方接收到消息后,解密算法使用私钥将密文解密。私钥只有接收方知道,所以只有接收方能解密。
- 第三方入侵者截获到加密消息,没有私钥也无法解密。
为什么不能加密解密都使用公钥呢?公钥加密解密的开销太大。对称加密的速度比公钥加密快很多。
SSL / TLS如何工作
TSL使用公钥密码术在发送方和接收方之间建立公共密钥,然后使用对称密钥密码术进行进一步通信。
一旦客户端和服务器都同意使用TLS协议,他们通过使用一个握手过程协商出一个有状态的连接以传输数据。通过握手,客户端和服务器协商各种参数用于创建安全连接:
客户端连接到服务器,发送Client Hello要求创建安全连接,握手开始
- Client Hello 消息内容
- 支持的TLS协议版本
- 并列出受支持的密码组合(加密算法和加密哈希函数)
- 客户端生成的随机数RNc(用于之后的session key)
服务器从列表中决定加密和散列函数,发送Server Hello
- Server Hello 消息内容
- 确认使用的TLS议版本,浏览器与服务器支持的版本不一致,服务器关闭通信
- 服务器生成的随机数RNs(用于之后的session key)
- 确认使用的加密算法和函数
服务器发回其数字证书,证书包括
- 服务器名称
- 授信机构(Certification Authentication)
- 服务器公钥(public key server)
客户端确认证书的有效性
服务器请求客户端公钥。客户端有证书则双向身份认证,无证书随机生成公钥。
客户端创建一个随机pre-master密钥,并使用服务端公钥对其加密,之后发给服务端
服务端接收到pre-master密钥。服务端和客户端基于pre-master密钥各自生成Master密钥和会话密钥(session key)
客户端发送”Change cipher spec”给服务端,表示客户端已经开始使用session key来对消息散列加密,同时发送”Client finished”消息
服务端接收到”Change cipher spec”,将其记录层状态转换为使用Session key对称加密。发送”Server finished”消息到客户端。
之后双方可以在建立的安全信道上进行数据交换,所有消息通过Session key进行对称加密。
任何一个步骤失败,TLS握手过程就会失败并断开连接。握手完毕后的连接是安全的,直到关闭连接。
对称加密保证了通信的私密性,公钥加密保证数据的完整性。
在传输层之上,建立了TLS协议,确保客户端和服务器之间的安全通信;在TLS之上,运行HTTP。
SSL的配置
如果在生产环境,要向用户提供服务,就要通过认证过程:通过证书颁发机构(Certification Authorities),颁发公共证书。
这些证书颁发机构将验证你的凭据,确保你符合声明的身份。通过后,CA向你颁发一个公钥和一个私钥,在服务器站点使用。因此,一旦CA发出公钥和私钥,公钥将由CA认证,然后公钥也将携带公钥证书。这个证书也就是你的服务发送给客户端的证书。
由于大多数浏览器都拥有这些CA的可信根证书,所以,他们将能够通过获取你的证书,然后在已知证书已由CA签名的情况下验证证书,生成你的私钥。这样,客户端建立起认证。
但在开发环境下,如何配置公钥和私钥?
使用OpenSSL生成自签名证书。
安装OpenSSL之后,在CMD窗口下
1 | C:\OpenSSL-Win64\bin\openssl.cfg // 打开openssl.cfg文件 |
Node配置HTTPS服务
bin文件夹下,更改www
文件如下
1 | . . . |
更改spp.js
文件
1 | app.all('*', (req, res, next) => { |