1. 基本概念
1.1 HTTP
超文本传输协议(HTTP,HyperText Transfer Protocol),是客户端浏览器或其他程序与Web服务器之间的应用层通信协议,一般使用80端口。
HTTP请求过程中,客户端与服务器之间没有任何身份确认的过程,数据全部明文传输,易遭到黑客的攻击。黑客可“劫持”客户端发出的请求,并冒充服务器返回任意信息给客户端,且不被客户端察觉。
HTTP传输面临的风险包括:
- 截取:通信内容被获取
- 篡改:通信内容被修改
- 伪造:非法实体冒充合法实体参与通信
1.2 HTTPs
安全超文本传输协议(HTTPS,Hypertext Transfer Protocol Secure),由HTTP+SSL/TLS构建的可进行加密传输、身份认证的网络协议,一般使用443端口。
安全套接字层(SSL,Secure Socket Layer)/传输层安全(TLS,Transport Layer Security)协议位于应用层和TCP层之间。应用层数据传递给SSL/TLS实现传输加密与身份认证,需要到CA申请证书。
2. 非对称加密+对称加密方案
2.1 实现方案
为了方防止通信内容被获取,可对传输内容进行加密。直接使用对称加密算法,存在密钥传输与管理上的问题,一般采用对称加密方式对通信内容进行加密,而采用非对称加密方式实现对称加密的密钥传递。
- 客户端:发起HTTPS请求
- 服务器:生成公钥/私钥对 Pu/Pr,并把公钥发给客户端
- 客户端:生成随机数K作为会话密钥,用收到的公钥Pu加密后发送给服务器
- 服务器:使用私钥Pr解密,得到会话密钥K
客户端和服务器通过对称加密算法,使用会话密钥K对通信数据进行加密
上述步骤中的会话密钥由客户端生成并且用服务器的公钥加密后发送至服务器,由于只有服务器才有私钥,因此也只有服务器才能解开客户端发送的密钥。
要确保传输的会话密钥只被服务器解密,就须确保用于加密会话密钥的公钥一定由服务器下发,绝对不可能被第三方篡改过。
2.2 中间人攻击
如果在数据传输过程中,中间人劫持到了数据,就可以在通信双方都不会发现异常的情况下,中间人通过将服务器的公钥替换为自己伪造的公钥,进而得到会话密钥K,其根本原因是浏览器无法确认收到的公钥是否来自服务器。
- 客户端:发起HTTPS请求
- 服务器:生成公钥/私钥对 Pu/Pr,并把公钥发给客户端
- 中间人:劫持到服务器发送的公钥Pu,并保存下来,然后将公钥Pu替换成自己伪造的公钥Pu‘(对应私钥为Pr’)发送给客户端。
- 客户端:生成随机数K作为会话密钥,用收到的公钥Pu‘加密K发送给服务器
- 中间人:劫持到秘文后,用私钥Pr’解密得到会话密钥K,再用服务器公钥Pu加密后传给服务器。
- 服务器:使用私钥Pr解密,得到会话密钥K
3. 基于SSL的实现
3.1 实现方案
要保客户端接收到的公钥为服务器真正的公钥(而不是中间人伪造的公钥),就需要引入公钥基础设施(PKI,Public Key Infrastructure),通过PKI的认证机构CA(Certificate Authority)为服务器签发的数字证书来实现。
服务器收到客户的https请求后,向客户端发送SSL证书,既解决了公钥获取问题,又解决了“中间人攻击”问题。SSL证书中包括:
- 证书的发布机构CA
- CA的数字签名(通过CA的私钥对证书的数字摘要加密生成)
- 证书的有效期
- 证书持有者身份信息
- 证书持有者的公钥
客户端接受到服务端发来的SSL证书,对证书进行校验,以浏览器为例说明如下:
(1)浏览器读取证书中的证书所有者、有效期等信息,并进行校验
(2)浏览器查找操作系统中内置的受信任证书发布机构CA,与服务器发来的证书中的颁发者CA比对,用于校验证书是否为合法机构颁发
(3)如果找不到,浏览器就会报错,说明服务器发来的证书是不可信任的
(4)如果找到,浏览器验证CA的数字签名(使用CA的公钥对服务器发来的证书中的CA数字签名进行解密),得到证书的hash值
(5)浏览器使用相同的hash算法计算出服务器发来的证书的hash值,将这个计算的hash值与证书中hash值做对比
(6)对比结果一致,则证明服务器发来的证书合法
(7)协商生成会话密钥,并用会话密钥加密通信数据
3.2 HTTPs的密钥协商
HTTPS一般采用RSA或者DH算法协商预主密钥(PreMaster Secret),通过预主密钥生成主密钥(Master secret),再用主密钥用来生成各类加密算法密钥。
(1)RSA
- 客户端向服务器端发起连接请求。
- 服务器端生成一个RSA密钥对,并将公钥发送给客户端。
- 客户端通过随机数生成器生成一个预备主密钥,用服务器的公钥加密并发送给服务器端。
- 服务器解密预备主密钥,假如能够正确解密,则说明客户端和服务器端共同协商出一个预备主密钥。
(2)DH 算法
DH 算法的预备主密钥是客户端和服务器端共同计算出来的,因此是一致的。
- 客户端向服务器端发起连接请求。
- 服务器端生成一个RSA密钥对,并将公钥发送给客户端。
- 服务器端生成DH参数和服务器DH密钥对,用RSA私钥签名DH参数和服务器 DH 公钥,将签名值、DH 参数、服务器 DH公钥发送给客户端。
- 客户端通过服务器RSA的公钥验证签名,获取到PH参数和服务器DH公钥。客户端通过DH参数生成客户端的DH密钥对,并将客户端DH公钥发送给服务器端。
- 客户端通过客户端 DH 私钥和服务器端 DH 公钥计算出预备主密钥。
- 服务器端接收到客户端的DH公钥,结合服务器的DH私钥计算出预备主密钥。