面试官:你了解数据安全传输吗?
鄢栋,微医云服务团队前端工程师。有志成为一名全栈开发工程师甚至架构师,路漫漫,吾求索。生活中通过健身释放压力,思考问题。
看到这个标题,很多老铁会斩钉截铁的说,这道题我会!就是用 HTTPS 来进行安全传输的。
对,很优秀,那你知道 HTTPS 底层是如何对数据进行安全保障的吗?下面就进入我们今天的主题介绍:HTTPS 是如何实现数据安全传输的。
HTTPS 认知
HTTPS 其实是 HTTP + SSL 协议组成的安全协议。
我们知道,从我们输入 URL 到页面呈现的过程是作用于 HTTP 协议的,HTTP 协议保证我们网络传输数据的基础,但是安全性无法保证,而 SSL 协议作用于 Http 协议就能解决安全问题。
HTTPS 保证以下三点:
数据内容加密 数据完整性保护(数字摘要、数字签名) 身份认证
HTTPS 保证安全性要点:
握手阶段:使用 非对称加密技术
对公钥
进行加密传输阶段:使用 对称加密技术
对报文
进行加密
由于 HTTPS 多了一层使用非对称加密算法对公钥进行加密的过程,因此建立连接的时间比 HTTP 要慢。
握手阶段保证了连接是安全的,那么后续的数据传输就可以安全的进行传输,因此可采用耗时较少的对称加密算法对报文进行加密传输。
HTTPS 解构
在上图中,我们看到 SSL 协议的作用,在了解保证数据安全的 SSL 协议之前,我们先了解一些关于数据安全涉及的一些概念。
加解密相关概念
对称加密
别名: 私钥加密、单密钥算法、传统密码算法。
概念: 指使用 相同的密钥
进行加解密,因此从加密密钥可以推算出解密密钥,也可以从解密密钥推算出加密密钥。
常见的对称加密算法: DES(Data Encryption Standard)、AES(Advanced Encryption Standard)、RC4、IDEA
非对称加密
别名: 公钥加密
概念: 公钥是对外公开的,私钥存储在通信两端的各自手里。客户端跟加密的公钥形成一对密钥对, 服务端跟加密的公钥形成另外一对密钥对,加解密的密钥是成对的
限制: 加密内容的长度不能超过公钥的长度
数字摘要
别名: 数字指纹
概念: 明文采用单项 Hash 函数生成的一串固定长度(128 位)的密文。
数字签名
概念:非对称密钥加密技术和数字摘要的混合应用
数字签名过程
1、发送者使用 Hash 函数 (H) 将原文生成数字摘要 A
2、发送者使用自己的私钥, 对数字摘要 A 进行加密, 生成密文 CypherA
3、将密文 CypherA 与原文一起传送给接收者
数字签名验证(信息的完整性)过程
1、接收者使用 Hash 函数 (H) 将接收到的原文生成数字摘要 B (B === A, H 函数是一样的)
2、接收者使用公钥,对接收到的加密密文 (CypherA) 进行解密, 得到数字摘要 B'
3、对比 B' 与 B 是否相等, 如果相等,说明收到的信息是完整的并且消息确实是由该发送方签名并发送的(因为私钥只有发送方自己知道),在传输过程中没有被修改;否则信息被修改
最后比较数字摘要 A 与数字摘要 A'是否相等,也可以逆向使用 Hash()函数,将摘要 A'进行还原得到明文,比较改明文与传过来的原文是否一致(都是 pig)。
数字签名
是个 加密
的过程,数字签名验证
是个 解密
的过程。一次数字签名涉及到一个哈希函数、接收者的公钥、发送方的[私钥]。
伪代码
// 单项 Hash 函数
fucntion Hash (plainText) { // 传入明文参数
// 明文加密过程
const encryptedAbstract = encrypt(plainText)
// 返回固定长度(128 位)的数字摘要
return encryptedAbstract
}
// 发送者使用自己的私钥对明文产生的数字摘要进行加密, 生成密文 CypherA
function doEncrypt (senderPrivateKey, encryptedAbstract) {
const CypherA = encrypt(senderPrivateKey, encryptedAbstract)
return CypherA
}
// 发送报文
function sendMessage (plainText) {
const encryptedAbstract = Hash(plainText)
const CypherA = doEncrypt(senderPrivateKey, encryptedAbstract) // 加密
return {
CypherText: CypherA,
originText: plainText
}
}
// 接收者用公钥解密
function doDecrypt (publicKey, encryptedAbstract) {
const decryptedAbstract = decrypt(publicKey, encryptedAbstract)
return decryptedAbstract
}
// 接收报文
function receiveMessage (CypherA, plainText) {
const encryptedAbstract = Hash(plainText)
const decryptedAbstract = doDecrypt(publicKey, encryptedAbstract) // 解密
if (decryptedAbstract === encryptedAbstract) {
console.log('1、the sender is true') // 消息发送者的确认
console.log('2、the message is complete') // 消息完整性的确认
}
}
const message = sendMessage(plainText) // 数字签名过程
receiveMessage (message.CypherText, message.originText) // 数字签名认证过程
数字证书
在上述数字签名的过程中,我们如何保证这个公钥是可信任的?这就是数字证书存在的必要性。
数字证书主要用于加密、签名、身份认证。
数字证书由 证书颁发机构(CA, Certification Agent)
颁发, CA 会在颁发证书之前以及使用证书时对持有者的身份进行验证,它让客户端有能力去识别公钥是否来自合法的服务器。
证书颁发机构(CA)
颁发包含公钥和所有者身份的数字证书。匹配的私钥不是公开的,而是由生成密钥对的最终用户保密。证书还是 CA 的确认或验证,证书中包含的公钥属于证书中标注的个人,组织,服务器或其他实体。CA 在此类方案中的义务是验证申请人的凭证,以便用户和信赖方可以信任 CA 证书中的信息。
当您访问使用 HTTPS(安全连接)的网站时,该网站的服务器会使用证书向浏览器(如 Chrome)证明该网站的身份。证书中包含的公钥信息是可信任的, 如果证书不存在、证书被篡改、证书失效等情况,浏览器会在左上角提示你该网站不安全。
签名验证链条:client <- 服务器 <- CA
数字证书的内容
证书颁发机构的名称 证书本身的数字签名 证书持有者公钥 证书签名用到的 Hash 算法 ... 等等
公钥和数字签名
了解这些基本概念后, 进入我们今天的主题:SSL 协议如何保障数据安全传输
SSL/TLS
SSL(Secure Socket Layer, 安全套接字层)
利用加密技术,确保数据在网络传输过程中不会被窃取。
TLS (Transport Layer Security,传输层安全协议)
用于两个应用程序之间提供保密性和数据完整性。
该协议建立在 SSL3.0 协议的基础之上,可理解为 SSL3.1 版本。只不过在 SSL3.0 的基础上采用了一些更安全的策略,让数据更加安全,其他的协议分层与功能与 SSL 一致。有兴趣的可自行了解其与 SSL 的区别与优势。
SSL/TLS 协议的作用:
数据加密,防止被窃取 保护数据的完整性,确保数据不会被改变 身份认证,确保数据被发送到正确的客户端和服务器
可以看到, 这正是 HTTPS 协议发挥作用的三点。
那么, SSL 协议到底是如何把我们数据进行加密,从而进行安全传输的呢?
SSL、TLS 的握手过程
1、客户端告知服务端自己支持的 安全协议版本(如 TLS1.0)
、加密算法
、压缩方法
、随机数 CRandom1
;
2、服务端首次响应,返回给客户端 安全协议的版本
、加密算法
、压缩方法
、随机数 SRandom
, 还有一个 数字证书(服务器证书)
;
3、客户端对服务端发送过来的证书进行验证,验证通过后,进行如下操作:
客户端再次产生一个随机数 CRandom2 使用服务器证书中的公钥对数据进行进行加密,生成随机数 CRandom3 发送 ChangeCipherSpec(编码改变)的消息通知(告知服务器我已经准备好用我们之前商量好的加密套件进行加密并传输数据了)
、前面所有消息的 hash 值
以及加密数据 CRandom3
进行服务器验证使用与服务器确认的加密算法对 CRandom1、CRandom2、CRandom3 三个随机数进行加密,生成 Session Secret(这个就是后边使用对称加密算法进行传输数据时所用到的对称加密密钥,还可用来 会话恢复
, 节约 SSL 的握手时间)
4、服务器再次响应:
使用自己的私钥对 CRandom3 进行解密、并对解密后的数据进行验证 发送 ChangeCipherSpec(编码改变)的消息通知(告知客户端我也准备好了用我们之前商量好的加密套件和 Session Secret 进行加密数据了)
使用 Session Secret 加密一段 Finish 的消息发送给客户端, 以验证之前通过握手建立起来的加解密通道是否成功
到上面四步,客户端与服务器已经确定了密钥,就可以对消息进行加密传输了。
到此,握手过程结束。
整个握手阶段的安全,取决于第三个随机数 CRandom3 能否被破解,因为这个随机数是使用服务端的公钥进行加密的、服务端的私钥进行解密的;而私钥只存储在了服务端本身。
在所有的握手阶段都完成之后,就可以使用对称加密技术开始传送应用数据了。
QA
1、客户端如何对接收到的证书进行验证的?
证书本身就已经告诉客户端怎么验证证书的真伪。也就是证书上写着如何根据证书的内容生成证书编号。客户端拿到证书后根据证书上的方法自己生成一个证书编号,如果生成的证书编号与证书上的证书编号相同,那么说明这个证书是真实的。
2、公钥的安全性是通过证书来确认的, 但是证书是由颁发机构来颁发的, 那如何确认这个颁发者是可信的呢?
通过证书链。
root:根证书,权威证书认证机构 (CA, Certificate Authority) 给自己颁发的数字证书,也就是自己认证自己。在上图中根证书就是由 DigiCert Global Root CA 自己给自己签发的。
intermediates:中间证书,根 CA 生成一对公钥、私钥,并用私钥将中间 CA 的信息和公钥进行 “加密” 生成签名,封装得到中间证书。需要注意的是,中间 CA 可能不止一个。上一级 CA 同样按照这个逻辑给下一级 CA 进行签发证书。在这里中间 CA 就是 RapidSSL RSA CA 2018,它给末端使用者签发证书。
end-user:末端使用者(证书)。图中的末端证书就是 *.juejin.im 使用的数字证书。
可以看到证书链由多个证书一层一层组成的。末端证书的公钥是给用户加密报文外,其他层证书中的公钥均用于解密下一层的证书指纹签名。最高层的根证书是自签名的,也就是自己颁发给自己,所以 根证书一定是可信的
(难道自己还不能信任自己吗?^^)
总结
网络安全传输数据依赖 SSL 协议,而网络传输的协议是 HTTP, 因此构成了 HTTPS 协议。而 HTTPS 要保证客户端与服务器端的高效通信安全,必须使用对称加密算法,但是协商对称加密算法的过程,需要使用非对称加密算法来保证安全,然而直接使用非对称加密的过程本身也不安全,会有中间人篡改公钥的可能性,所以客户端与服务器不直接使用公钥,而是使用数字证书签发机构颁发的证书来保证非对称加密过程本身的安全。这样通过这些机制协商出一个对称加密算法,就此双方使用该算法对数据进行加密解密传输,从而解决了客户端与服务器端之间的通信安全问题。
笔者简单带大家了解了数据安全传输的关键点, 其实关于安全的话题还有很多值得深入的点,欢迎大家给我留言~ 共同学习,共同进步。创作不易,如果本文对你有那么一点点帮助的话, 点个赞送我上热搜(#^.^#),让我有更多的动力继续创作~
参考资料
SSL/TLS 协议详解:https://cshihong.github.io/2019/05/09/SSL%E5%8D%8F%E8%AE%AE%E8%AF%A6%E8%A7%A3/
最后
如果你觉得这篇内容对你挺有启发,我想邀请你帮我三个小忙:
点个「在看」,让更多的人也能看到这篇内容(喜欢不点在看,都是耍流氓 -_-)
欢迎加我微信「qianyu443033099」拉你进技术群,长期交流学习...
关注公众号「前端下午茶」,持续为你推送精选好文,也可以加我为好友,随时聊骚。