HTTPS
HTTP 缺点:
- 通信使用明文(不加密),内容可能会被窃听;
- 不验证通信方的身份,因此有可能遭遇伪装;
- 无法证明报文的完整性,所以有可能已遭篡改;
为了统一解决上述这些问题,需要在 HTTP 上加入加密和认证等机制。即把添加了加密及认证机制的 HTTP 称为 HTTPS(HTTP Secure)。
HTTPS
HTTPS 并非是应用层的一种新协议,而是 HTTP 通信接口部分用 SSL 或 TLS 协议代替而已。 在采用 SSL 后,HTTP 就拥有了加密、证书和完整性保护这些功能。
通常,HTTP 直接和 TCP 通信。当使用 SSL 时,则演变成先和 SSL通信,再由 SSL和 TCP 通信。
SSL: Secure Socket Layer,安全套接层,主要任务是提供私密性,信息完整性和身份认证。SSL 独立于 HTTP 协议,位于TCP/IP协议与各种应用层协议之间,其他运行在应用层的 SMTP 和 Telnet 等协议均可配合 SSL 协议使用。SSL 是当今世界上应用最为广泛的网络安全技术。具体可查看 SSL/TLS协议详解
TLS: Transport Layer Security,安全层传输协议
HTTPS:HTTP Secure,超文本传输安全协议
HTTPS 混合加密机制
HTTPS 采用对称加密与非对称加密两者并用的混合加密机制,充分利用了两者各自的优势。
对称加密
加密和解密使用同一个密钥的方式称为对称加密。
对称加密时必须将密钥也发给对方。
为什么不只采用对称加密?
如果通信双方都各自持有同一个密钥,且没有泄漏出去,则这两方的通信就是安全的。然而问题是如何让传输双方都安全的知道密钥?。
如果由服务器生成一个密钥并传输给浏览器,此时通信被监听,那么密钥就可能会落入攻击者之手,就失去了加密的意义。
如果浏览器内部预存了网站 A 的密钥,且可以确保除了浏览器和网站A,不会有任何一方知道该密钥,理论上用对称加密是可以的。只要浏览器预存好世界上所有 HTTPS 网站的密钥就行了!这么做显然不现实。
非对称加密
非对称加密很好地解决了对称加密的缺点。加密和解密使用不同密钥的方式称为非对称加密。
所以非对称加密有两把密钥,一把是私有密钥(private key),另一把是公开密钥(public key)。私钥加密的信息只有公钥才能解开, 公钥加密的信息只有私钥可以解开。为什么会这样呢?因为RSA算法。
RSA 算法
RSA 算法计算流程如下:
- 随机选取两个质数p和q
- 计算 n = pq
- 计算 φ(n) = (p-1)(q-1)
- 找一个与φ(n)互质的小奇数e,互质是指两个数的公约数只有1
- 对模φ(n),计算e的乘法逆元d,即找到一个d,使下列等式成立:(e*d) mod φ(n) = 1
- 得到公钥:(e, n),私钥: (d, n)
- 加密过程:c = (m^e) mod n, (c为加密后的密文,m为原文)
- 解密过程:m = (c^d) mod n
为什么公钥自己加密的数据自己还解不出来?因为加密算法(m^e) mod n
是模运算,模运算是不能反解的。例如 5 对 4 取模,5 % 4 =1 ,但是反过来,知道 x % 4 = 1,求 x。这个x可以有无限个,5,9,13... 所以即使有公钥(e,n) 和密文 c,也不知道(m^e) 到底取哪个值,这就是非对称加密的核心机密。私钥加密同理,自己加密的自己也反解不出来。
为什么不只采用非对称加密?
因为非对称加密非常耗时,效率低,而对称加密会快很多,所以应尽量减少非对称加密的次数。
混合加密机制的请求过程
- 某网站拥有用于非对称加密的公钥A、私钥A’。
- 浏览器请求该网站服务器,服务器把公钥A 明文 传输到浏览器。
- 浏览器随机生成一个用于对称加密的密钥 X,用公钥 A 加密后传给服务器。
- 服务器拿到后用私钥A’ 解密得到密钥 X。
- 双方都拥有密钥X,之后双方所有数据都通过密钥 X 加密解密即可。
为什么公钥明文传输?
如果对公钥加密传输,就变成了变成鸡生蛋、蛋生鸡的问题...
此时看起来一切都很完美,但是如何证明浏览器收到的公钥一定是该网站的公钥呢?如果请求被攻击:
- 某网站有用于非对称加密的公钥A、私钥A’。
- 浏览器向网站服务器请求,服务器把公钥A 明文 传输到浏览器。
- 攻击者劫持到公钥 A,保存下来,把数据包中的公钥A 替换成伪造的公钥B(攻击者拥有公钥B 对应的私钥 B’)。
- 浏览器生成一个用于对称加密的密钥X,用公钥B(浏览器无法得知公钥被替换了)加密后传给服务器。
- 攻击者劫持后用私钥B’ 解密得到密钥 X,再用公钥A 加密后传给服务器。
- 服务器拿到后用私钥A’ 解密得到密钥 X。
此时双方都不会发现异常。造成这种情况的根本原因是浏览器无法确认收到的公钥是不是正确的。
数字证书
综上所述,浏览器无法证明收到的公钥是该网站的公钥。为了解决这个问题,就出现了数字证书。数字证书是由数字证书认证机构(CA,Certificate Authority)给服务端颁发的。(CA机构是客户端与服务器双方都可信赖的第三方权威机构。)
CA机构通过服务端提供的相关信息生成证书,一个数字证书通常包含了:
- 公钥;
- 持有者信息;
- 证书认证机构(CA)的信息;
- CA 对这份文件的数字签名及使用的算法;
- 证书有效期;
- 其他额外信息...
浏览器控制台可以看数字证书。百度的数字证书如下:
如何防止证书被篡改?
为了避免对证书内容的篡改,出现了数字签名 Certificate Signature。 CA 机构把网站的公钥、用途、颁发者、有效时间等基本信息打成一个包,然后对这些信息进行 Hash 计算,得到一个 Hash 值;然后 CA 机构使用自己的私钥将该 Hash 值加密生成数字签名,也就是 CA 对证书做了签名。
业务流程
- 服务器向 CA 机构提出数字证书的申请,CA 机构在判明提出申请者的身份之后,将公钥、用途、颁发者、有效时间,数字签名,散列算法等信息生成数字证书,并发送给服务端。
- 服务器会将这份数字证书发送给客户端, 接到证书的客户端使用 CA机构的公开密钥,对数字证书进行验证。
客户端使用同样的 Hash 算法获取该证书的 Hash 值 H1;使用 CA 的公钥解密数字签名得到一个 Hash 值 H2 ;比较 H1 和 H2,如果值相同,则为可信赖的证书,否则则认为证书不可信。
如果证书验证通过,客户端便可明确两件事:- 认证服务器的公开密钥的是真实有效的数字证书认证机构。
- 数字证书的公开密钥是值得信赖的。
- 证书验证通过后,客户端生成用于对称加密的密钥X,用公钥加密后传给服务器。
- 服务器拿到后用私钥A 解密得到密钥 X。之后的通信就由密钥X 实现加密解密。
为什么制作数字签名时需要 hash?
因为进行 hash 算法之后得到的是一个定长的 hash 码(比如用 md5 算法 hash 后可以得到固定的128位的值)。接受者用私钥解密出来的得到一个 hash 码,再用 hash 算法对消息内容进行 hash 得到一个新的 hash 码,只需要比较解密出来的 hash 码和 hash 内容出来的两个定长 hash码就可以;这样做比起没有hash,直接加密和解密消息内容性能更好。
怎么证明 CA 机构的公钥是可信的?
CA 机构的公开密钥必须安全地转交给客户端。使用通信方式时,如何安全转交是一件很困难的事,因此,多数浏览器会事先在内部植入常用认证机关的公开密钥。以此来保证 CA 机构的公钥是可信的。(鸡生蛋 蛋生鸡的问题...)
证书链
敬请期待~~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。