https - TLS 密钥交换
TLS密钥交换
TLS在握手时密钥的协商和交换是关键且耗时的一个步骤,密钥交换中有2个重点问题:
- (1)密钥周期要尽可能短,密钥周期一个会话一个密钥(这个一般是不能达到的)
- (2)密钥不能明文传输,一旦被窃听所有的努力都将白费。
既然密钥不能明文传递,那么如何确保密钥在网络传递过程中被窃取后依然无法得到真正的密钥,这里就需要使用非对称加密。它的特点是公钥加密的数据,只用私钥能解密。
基于RSA的密钥交换
- 服务器拥有私钥和公钥(私钥只能服务端持有),服务器把自己公钥以明文形式的发给客户端;
- 客户端生成一个密钥并使用公钥加密,并将加密后的密钥传递给服务端。注意:在传递的过程中即使密钥被截获,但由于无法获取私钥而不能将真正的密钥解密。也就是说,密钥只能由服务端使用私钥进行解密。
- 服务端获取使用公钥加密后的密钥,并使用自己的私钥对其解密得到密钥。这样就完成了密钥交换。
非对称算法是基于某个数学难题的(私钥在服务器端,公钥一般在证书中)。
- A对服务器B发起请求,B首先把公钥(包含在证书中)发给A(明文传输,证书是公开的)。
- A使用随机数算法,生成1个密钥key,并使用公钥进行加密,生成e(key),把e(key)发送到服务器B。
- B收到e(key),使用私钥进行解密从而得到key。 交换后,客户端和服务器都得到了密钥key(预主密钥)。
说明:B发送公钥在TLS中是通过certificate报文发送的certificate中的包含了公钥。密钥是通过Client key exchange报文发送的。
注意:
-
在实际TLS中,key并没有直接被当成密钥,为了描述运行过程,省去了对key后续进行KDF等操作。在TLS中,会话安全性取决于称为主密钥(master secret)的48字节共享密钥。密钥交换的目的是计算另一个值,即预主密钥(premaster secret)。这个值是组成主密钥的来源。
-
上面所说的证书而并非我们在百度浏览器中看到的证书。百度中的证书中包含的公钥只是用来进行身份验证的,可不是用在密钥交换里面的。
- AES_128_GCM:用于加密
- ECDHE_RSA:用于身份验证
基于DH类算法的密钥交换
RSA的密钥算法中最大的特点就是密钥的安全取决于私钥的安全,一旦私钥外泄,那么第三方就能从之前所有的e(key)中解密得到所有之前的key,这样就可以破解所有之前监听得到的密文。
如此A与B之前所有的保密通信都归零了。这就是所谓的不支持前向安全(forward secrecy)。
ECDHE(DHE)算法属于DH类密钥交换算法,这里的E表示临时, 私钥不参与密钥交换,即使私钥外泄,加密的报文都无法被解密,实现了前向安全(forward secrity)。由于ECDHE每条会话都重新计算一个密钥,所以当一个会话被解密后,其他会话仍旧安全。
DHE算法交换秘钥流程
临时Diffie-Hellman(ephemeral Diffie-Hellman,DHE)密钥交换是一种构造完备的算法。它的优点是支持前向保密,缺点是执行缓慢。
-
客户端A生成1个随机值x,使用x作为指数,即计算a = g^x mod p (g的x次方对p取模),p 是个大素数,g是生成数。客户端把 a发送至服务器,x 作为自己私钥,且只有A自己知道。
-
服务器B和客户端A流程一样,生成一个随机值y,用y作为指数,计算b = g^y mod p,将结果b发送至客户端,y自己保存。
-
客户端A收到 b 后计算key1 = b^x mod p
-
服务器B收到 a 后计算key2 = a^y mod p
根据数学定理 key1 = ((g^y mod p)^x )mod p = g^yx mod p key2= ((g^x mod p)^y )mod p = g^xy mod p g^xy = g^yx ,所以 key1 = key2 ,密钥交换成功,而且中间没有传输A B双方私有的 x与y , 传输的只是 p ,g ,g^x mod p , g^y mod p ,在已知这四个数的情况下是很难得出 x与y的,这是依赖于离散对数这个难题。
说明:
DHE密钥交换时并未有私钥参与进来,而密钥是被重新计算出来的,就算密钥被泄漏,之前的通信还是安全的,具有前向保密性;即使是某一次的密钥外泄(也就是 x和y外泄),那么之前的加密数据也不会遭遇危险,因为每次都生成不同的x与y。
ECDHE算法交换密钥流程
理解了DHE密钥交换,那么理解ECDHE密钥交换原理并不难。数学方面的问题不深究也能理解。就是ECDHE的运算是把DHE中模幂运算替换成了点乘运算,速度更快,想破解更难。 临时椭圆曲线Diffie-Hellman(ephemeral elliptic curve Diffie-Hellman,ECDHE)密钥交换建立在椭圆曲线加密的基础之上。椭圆曲线算法是相对较新的算法。 流程如下:
- 客户端A随机生成随机值a,计算F(x, y) = a * Q(x, y),将F(x, y)发送至服务器B。
- 服务器B随机生成随机值b,计算F(x,y) =b * Q(x, y)。将F(x, y)发送至客户端A。
- 客户端A计算key1(x, y) = a * (b * Q(x, y)) 。
- 服务器计算key2(x, y) = b *(a * Q(x, y)) 。 key1 = key2 = key,取key的x向量作为密钥(预主密钥)。 Q(x, y)为公认的某个椭圆曲线算法的基点。例如 secp256k1 与 secp384r1
ECDHE密钥交换中,椭圆曲线(例如secp256k1) 和b通过server key exchange报文发送;a通过client key exchange报文发送。
椭圆曲线参数:
[root@framework ~]# openssl ecparam -list_curves
secp256k1 : SECG curve over a 256 bit prime field
secp384r1 : NIST/SECG curve over a 384 bit prime field
secp521r1 : NIST/SECG curve over a 521 bit prime field
prime256v1: X9.62/SECG curve over a 256 bit prime field
secp256k1和prime256v1是用的比较多的。
总结
密钥交换:RSA进行密钥交换是不支持前向安全的,一旦私钥泄露,则在传输中的所有数据都是不安全的。DH、DHE、ECDHE也都是可以用于密钥交换的。其中ECDHE的速度会更快,安全性也更高。
- DHE:DH->算法;E->表示临时,表示每次会重新计算密钥,也就支持了前向保密,缺点就是速度比较慢。基于的数学难题就是离散对数。
- ECDHE:EC->椭圆曲线;DH->算法;E->表示临时,可支持前向加密
- ECDH:没有E,非临时,不会重新计算x和y,不支持前向加密。ECDH算法服务器端的私钥是固定的,即证书的私钥作为b,故ECDH不被认为前向安全,因为私钥泄漏相当于b泄漏,可以使用b计算出之前所有的密钥。
在密钥交换时,由服务器端生成密钥交换参数,发送给客户端。但是RSA是不需要发送密钥交换参数的。因为服务器端可以通过私钥解密出客户端发送的预主密钥再通过算法生成主密钥。整个过程无需发送额外的参数。
推荐阅读
-
Qt中https的使用,报错TLS initialization failed和不能打开ssl.lib问题解决
-
针对 HTTPS 地址和 TLS 知识摘要的 C# 请求故障分析
-
PKI 系统下的 SSL TLS HTTPS 详情
-
https - TLS 密钥交换
-
隐私计算密码学基础系列 - Diffie-Hellman 密钥交换
-
vmwareworkstation16 密钥共享 vm16 虚拟机激活许可证完整版 https://www.win7zhijia.cn/win10jc/win10_48440.html
-
问希尔如何进行加密密钥交换?
-
ssh工作流程及原理-SSH(Secure Shell Protocol,安全的壳程序协议),它可以通过数据包加密技术将等待传输的数据包加密后再传输到网络上。ssh协议本身提供两个服务器功能:一个是类似telnet的远程连接使用shell的服务器;另一个就是类似ftp服务的sftp-server,提供更安全的ftp服务。 连接加密技术简介 目前常见的网络数据包加密技术通常是通过“非对称密钥系统”来处理的。主要通过两把不一样的公钥与私钥来进行加密与解密的过程。 公钥(public key):提供给远程主机进行数据加密的行为,所有人都可获得你的公钥来将数据加密。 私钥(private key):远程主机使用你的公钥加密的数据,在本地端就能够使用私钥来进行解密。私钥只有自己拥有。 SSH工作过程:在整个通讯过程中,为实现SSH的安全连接,服务端与客户端要经历如下五个阶段: 版本号协商阶段 SSH目前包括SSH1和SSH2两个版本,双方通过版本协商确定使用的版本 密钥和算法协商阶段 SSH支持多种加密算法,双方根据本端和对端支持的算法,协商出最终使用的算法 认证阶段 SSH客户端向服务器端发起认证请求,服务器端对客户端进行认证 会话请求阶段 认证通过后,客户端向服务器端发送会话请求 交互会话阶段 会话请求通过后,服务器端和客户端进行信息的交互 一、版本协商阶段 服务器端打开端口22,等待客户端连接; 客户端向服务器端发起TCP初始连接请求,TCP连接建立后,服务器向客户端发送第一个报文,包括版本标志字符串,格式为“SSH-<主协议版本号>.<次协议版本号>.<软件版本号>”,协议版本号由主版本号和次版本号组成,软件版本号主要是为调试使用。 客户端收到报文后,解析该数据包,如果服务器的协议版本号比自己的低,且客户端能支持服务器端的低版本,就使用服务器端的低版本协议号,否则使用自己的协议版本号。 客户端回应服务器一个报文,包含了客户端决定使用的协议版本号。服务器比较客户端发来的版本号,决定是否能同客户端一起工作。如果协商成功,则进入密钥和算法协商阶段,否则服务器断开TCP连接。 说明:上述报文都是采用明文方式传输。 二、密钥和算法协商阶段 服务器端和客户端分别发送算法协商报文给对端,报文中包含自己支持的公钥算法列表、加密算法列表、MAC(Message Authentication Code,消息验证码)算法列表、压缩算法列表等等。 服务器端和客户端根据对端和本端支持的算法列表得出最终使用的算法。 服务器端和客户端利用DH交换(Diffie-Hellman Exchange)算法、主机密钥对等参数,生成会话密钥和会话ID。 由此,服务器端和客户端就取得了相同的会话密钥和会话ID。对于后续传输的数据,两端都会使用会话密钥进行加密和解密,保证了数据传送的安全。在认证阶段,两端会使用会话用于认证过程。 会话密钥的生成: 客户端需要使用适当的客户端程序来请求连接服务器,服务器将服务器的公钥发送给客户端。(服务器的公钥产生过程:服务器每次启动sshd服务时,该服务会主动去找/etc/ssh/ssh_host*文件,若系统刚装完,由于没有这些公钥文件,因此sshd会主动去计算出这些需要的公钥文件,同时也会计算出服务器自己所需要的私钥文件。) 服务器生成会话ID,并将会话ID发给客户端。 若客户端第一次连接到此服务器,则会将服务器的公钥数据记录到客户端的用户主目录内的~/.ssh/known_hosts。若是已经记录过该服务器的公钥数据,则客户端会去比对此次接收到的与之前的记录是否有差异。客户端生成会话密钥,并用服务器的公钥加密后,发送给服务器。 ****服务器用自己的私钥将收到的数据解密,获得会话密钥。 服务器和客户端都知道了会话密钥,以后的传输都将被会话密钥加密。 三、认证阶段 SSH提供两种认证方法: 基于口令的认证(password认证):客户端向服务器发出password认证请求,将用户名和密码加密后发送给服务器,服务器将该信息解密后得到用户名和密码的明文,与设备上保存的用户名和密码进行比较,并返回认证成功或失败消息。 基于密钥的认证(publickey认证):客户端产生一对公共密钥,将公钥保存到将要登录的服务器上的那个账号的家目录的.ssh/authorized_keys文件中。认证阶段:客户端首先将公钥传给服务器端。服务器端收到公钥后会与本地该账号家目录下的authorized_keys中的公钥进行对比,如果不相同,则认证失败;否则服务端生成一段随机字符串,并先后用客户端公钥和会话密钥对其加密,发送给客户端。客户端收到后将解密后的随机字符串用会话密钥发送给服务器。如果发回的字符串与服务器端之前生成的一样,则认证通过,否则,认证失败。 注:服务器端对客户端进行认证,如果认证失败,则向客户端发送认证失败消息,其中包含可以再次认证的方法列表。客户端从认证方法列表中选取一种认证方法再次进行认证,该过程反复进行。直到认证成功或者认证次数达到上限,服务器关闭连接为止。实例
-
SSH 协议理论解释 - SSH 传输层协议 - 主要用于 SSH 版本协商、算法协商和密钥交换
-
ssh 密钥交换细节和实现 diffie-hellman-group-exchange-sha