HTTPS原理
https工作原理
http是应用层协议,负责对数据的包装,下面一层是传输协议TCP,负责数据传输(数据明文传输)
https其实就是http和TCP之间多了一层加密层 TLS/SSL,在数据传输之前进行一次加密处理
下面介绍下https的流程演变
首先假设有client和server要进行通信,如何保证两者之间的通信安全
1、首先想到的是对通信的内容加密,使用对称加密算法,client和server都持有相同的密钥,通过这个密钥进行加密和解密,只要这个密钥不公开给其他人,就能保证client和server之间的通信安全;但是这里面我们只考虑了一个客户端和服务器端的通信,实际情况下一台服务器会和很多客户端通信,这样的话如果服务器和每个客户端都使用相同的密钥的话,那对于一些恶意的组织也会知晓这个密钥,这个密钥就没有意义了,所以需要服务器和每个客户端的密钥都不相同,使用不同的对称加密算法,并且需要server通过安全的通信向client传输密钥;
2、如何安全的传输密钥,需要通过非对称加密算法(私钥加密后的密文,只要是公钥,都可以解密,但是公钥加密后的密文,只有私钥可以解密。私钥只有一个人有,而公钥可以发给所有的人。)这样的话就可以保证客户端发向服务器端的过程是安全的(因为客户端发送的消息经过公钥加密后只能通过服务器的私钥解密,而服务器发往客户端的过程不是安全的,因为服务器发往客户端的消息可能被恶意第三方拦截,并且通过公钥解密获取信息),客户端可以通过使用服务器端给出的公钥对密钥加密,然后发给服务器端,这样的话即使加密后的密钥被恶意组织获取,没有服务器的私钥,也没办法进行解密获取密钥
3、现在需要考虑服务器如何将公钥安全的传给客户端,如果服务器直接将公钥传给客户端的话可能会存在中间人拦截的问题,客户端请求公钥的时候,被中间人拦截,中间人伪造成客户端向服务器请求公钥,服务器向中间人传送公钥,中间人将自己的公钥传递给客户端,这样的话其实客户端是在和中间人进行通信,传递信息的时候,客户端用假公钥加密信息传递给中间人,中间人使用私钥解密获取消息内容,并用真公钥加密假的消息传递给服务器,服务器使用私钥解密获取到假的消息内容,服务器使用私钥加密消息内容传给中间人,中间人利用真公钥解密获取消息内容,中间人用自己的私钥加密消息内容传递给客户端,客户端使用假公钥解密获取假的消息内容
4、对于上面的问题可以使用数字证书解决中间人问题;我们不能直接将服务器的公钥传递给客户端,而是第三方机构使用它的私钥对我们的公钥进行加密后(申请数字证书),再传给客户端。客户端再使用第三方机构的公钥进行解密。这样的话保证了中间人攻击失效,因为如果中间人用自己的私钥对消息加密,那么客户端使用第三方公钥没有办法对消息解密,浏览器和操作系统维护着一些第三方认证机构的列表(包括他们的公钥)
数字证书:
证书相当于网站的身份证,里面包含网站的各种信息和过期时间,当客户端访问服务器的时候,服务器会首先给客户端传递服务器证书(这个是向CA证书颁发机构申请获取的)
客户端接收到证书后,使用其本身所信任的CA颁发机构提供的公钥进行解密,如果解密成功则说明没有被掉包
证书一般都包含以下内容:
1.颁发证书的机构的名称 --CA
2.证书内容的本身数字签名,使用私钥加密
3.证书公钥
4.证书签名用到的算法
根证书:
每个浏览器都有一个根证书库,有的浏览器是采用自主的根证书库,而一些浏览器则采取第三方的根证书库,而根证书库是下载客户端浏览器时预先加载根证书的合集(chrome和ie是直接使用系统证书存储库)
数字签名:
一般来说使用公钥和私钥就可以做到不可抵赖性和不可篡改性,server使用私钥对报文加密,client使用server提供的公钥进行解密,如果顺利解密,就说明报文发送者一定是server
同时也能说明报文没有被篡改,应为如果要篡改报文需要使用server的私钥进行加密处理,这样client才能顺利解密。
但是由于传输的文件可能很大,为了证明文件的不可抵赖性和不可篡改性,需要对整个文件进行加密,由于非对称算法效率较低,这样做的代价太大。
对数字证书进行验证时会使用数字签名验证证书的真伪和完整性
数据在浏览器和服务器之间传输时,有可能在传输过程中被冒充的盗贼把内容替换了,那么如何保证数据是真实服务器发送的而不被调包呢,同时如何保证传输的数据没有被人篡改呢,要解决这两个问题就必须用到数字签名,数字签名就是用于验证传输的内容是不是真实服务器发送的数据,发送的数据有没有被篡改过
首先server将证书进行hash处理后得到一个摘要,摘要信息使用服务器私钥加密(不对报文加密,防止报文过大,加密效率低)之后就生成签名,服务器把签名连同报文一起发送给客户端。
客户端接收到数据后,把签名提取出来用公钥解密,如果能正常的解密出来摘要,那么就能确认是对方发的。
再把摘要提取出来做同样的Hash处理,得到的摘要信息,与之前解密出来的摘要对比,如果两者相等,就表示内容没有被篡改,否则内容就是被人改过了。
因此常规的做法是用到信息摘要和数字签名的方式。
不过我们可能会忽略一个问题,就是中间人也可以向第三方机构申请证书,当服务器先向第三方机构申请证书,然后传给客户端,被中间人截获,中间人将自己申请的证书发给客户端,客户端使用维护的第三方机构的公钥进行解密,可以正常解密,所以认为没有问题,然后客户端向中间人发送密钥,中间人再向服务器发送自己的密钥即假的密钥,这样的话实际上客户端还是和中间人在通信,中间人和服务器通信。所以我们一定慎重添加一些证书到我们受信任的证书里面
这是使用fiddler抓取https内容的一个实例:
上一篇介绍了htps通过数字证书来防止中间人攻击,服务器向第三方认证颁发机构申请数字证书(第三方机构使用私钥对证书信息加密)
之后服务器将数字证书发送到客户端,客户端使用本地维护的第三方机构公钥对数字证书进行解密,如果能够解密,说明证书没有被掉包
但是其中可能会忽略掉一个问题,就是中间人也可以像第三方认证机构申请数字证书,而且它申请的证书在客户端也能被正确的解密,
从而实现中间人攻击,所以对于证书的导入一定要慎重,下面使用fiddler充当中间人实现这个过程
首先下载fiddler(如果之前安装过fiddler,需要先清除系统中fiddler相关的证书,通过运行certmgr.msc删除fiddler相关证书)
然后下载fiddlercertmaker证书生成器(可以从官网下载,下载后安装)
然后打开fiddler > 打开工具栏tools里面的options,如下图
勾选decrypt https traffic ,会提示确实是否信任fiddler所生成的证书,一路点击是
然后点击actions中的 export root certificate to desktop将证书导出到桌面
打开浏览器证书管理,导入刚才所导出的证书,如下:
最后重启fiddler就可以捕获https请求,并且可以看到解密后的明文
大概原理如下,在这个过程中fiddler充当中间人的角色,对于浏览器来说相当于服务器,对于真实服务器来说相当于客户端
首先浏览器向真实服务器发送建立连接的请求时被fiddler拦截,fiddler充当服务器向浏览器发送一个证书,同时向真实服务器发送建立请求连接
由于之前已经将fiddler的根证书添加到客户端了,所以客户端在验证fiddler发送过来的证书时使用fiddler根证书验证,验证通过,建立连接协商密钥
进行数据传输,同时fiddler也会和真实服务器建立连接,协商密钥进行数据传输,这样的话fiddler就能获取到https传输的数据,同时也可以进行请求数据的更改
达成攻击
流程图如下
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了