浅谈TLS协议

1.什么是协议?

网络协议通俗的讲是网络上两台计算机之间通信所要共同遵守的标准。协议规定了一种信息交流的格式和规范。协议本身并不是一种软件,只是一种通信的标准,协议最终需要由软件来实现,网络协议的实现就是在不同的软件和硬件环境下,执行可运行于开中环境的“协议”翻译程序。说白了就是软件要实现这个协议翻译程序,从而使双方遵守这某一协议。不同的网络交互软件的功能可能不同,但是都会翻译同一种网络协议。实现网络协议,就像是给所有接入网络的设备配备了一个“通用语言翻译器”,这些翻译都懂通用语言:例如国际上的英语,同时它也懂得本国的语言。这样就能实现不同国家不同环境的人接入同一个网络并进行交流。
协议分层:我用英语说:“How are you.” 不一定表示“你好!”,我们可以事先约定,这句话表示“再看一遍”的意思。这就象是所谓的江湖“黑话”,或叫“专业术语”。实际上,这时我们自己制定了一个新的通信标准,一个新的“高层协议”己经诞生了。这个协议在“英语”的基础上,再制定自己的通信标准,这种新的通信标准就是基于“英语”这种“底层协议”的“高层协议”,我们可以把这种协议取名为“讲课协议”。说白了协议的分层就是在一个既定的协议之上再添加某些限定条件。创造一个新的协议。比如果规定双方用英语交流,那么在使用英语交流的过程中,对英语中的“Hello”单词,定义他的意思是”帅哥“。那么它在双方交流的时候就被理解为帅哥的意思。这就是又制定了一个新的协议。协议除了分层之外,还可以组合,比如将IP协议,TCP协议以及UDP协议组合在一起称为TCP/IP协议。
所以说下面的SSL协议就是在TCP协议的基础上,又对信息传输做了某些规定,从而产生的一种新的协议。

2.什么是HTTPS协议

由于http明文传输,很不安全所以出现了https.http“调用”SSL/TLS中的加密算法和协议逻辑,实现保密传输。https不能说是一个协议,只能说是一种应用。SSL加密http中的内容。然后默认使用433端口进行传输,SSL还可以加密Email,默认使用955,465端口。任何一个应用层协议都可以调用TLS/SSL来加密其明文数据。
所以简单总结就是 : https = http + SSL/TLS

3.什么是SSL协议?

SSL协议是Netscape研发的,保障在Internet上数据传输安全的一个协议,它利用数据加密技术,可以确保数据在网络上的传输过程不被截取或者窃听。被广泛应用于Web浏览器和服务器之间的身份认证和加密数据传输。SSL协议位于TCP/IP协议与各种应用层协议之间。为数据通讯提供安全支持。SSL协议可以分为两层:SSL记录协议:建立在可靠的传输协议(如TCP)上,为高层协议提供数据封装,压缩,加密,解密基本功能。SSL握手协议:建立在SSL记录协议止尚,用于在实际的数据传输开始之前,通讯双方进行身份验证,协商加密算法,交换加密密钥等。

4.什么是TLS协议?

TLS协议是SSL协议经历了SSL1.0,2.0,3.0版本后发展成为的一种新的安全标准协议。TLS有1.0,1.1,1.2,1.3这几个版本
TLS全称是安全传输层协议,用于在两个通信应用程序之间提供保密性和数据完整性。该协议由两层组成:TLS记录协议,TLS握手协议,较底层的是TLS记录协议。位于某个可靠的传输协议(如TCP)之上。
一次加密通信需要实现3个任务:机密性,完整性,身份认证。

5.TLS与SSL的区别都有什么?

TLS的最大优势在于:TLS是独立于应用协议。高层协议可以同名地分布再TLS协议上面。然后,TLS标准并没有规定应用程序如何在TLS上增加安全性。它如何启动TLS握手协议以及如何解释交换的认证证书的决定权流给协议的设计者和实施者来判断。
版本号:TLS记录合适与SSL记录格式相同,但是版本号值不同,TLS的版本1.0使用的版本号为SSLV3.1.
报文鉴别码:SSLv3.0和TLS的MAC算法记忆MAC计算的范围不同。TLS使用RFC-2140定义的HMAC算法。SSLv3.0使用了相似的算法,两者的主要差别在于SSLv3.0中,填充字节与密钥之间采用的是连接运算。而HMAC算法采用的是异或运算,两者的安全程度是相同的。
伪随机函数:TLS使用了成为PRF的伪随机函数来将密钥扩展为数据块,是更安全的方式。
报警代码:TLS支持几乎所有的SSLv3.0报警代码。而且TLS还补充定义了很多报警代码。如解密失败,记录溢出,位置CA,拒绝访问等。
密文族和客户证书:SSLv3.0和TLS存在少量差别,即TLS不支持Fortezza密钥交换,加密算法和客户证书。
Certificate_verify和finished消息;SSLv3.0和TLS在用certificate_verify消息计算MD5和SHA-1散列码时,计算的输入有稍许差别,但安全性相当。
加密计算:TLS和SSLv3.0在计算主密值时采用的方式不同。
填充:用户数据加密之前需要增加的填充字节。在SSL中,填充后的数据长度达到密文块长度的最小整数倍。而在TLS中,填充后的数据长度可以是密文块长度的任意整数倍(但填充的最大长度为255字节),这种方式可以防止基于对报文长度进行分析的攻击。

6.TLS/SSL在网络通信模型中的位置。

(1)在TCP/IP协议层中
在这里插入图片描述
(2)在OSI协议层中
在这里插入图片描述

7.TLS的结构

其实现上分为记录层和握手层两部分,其中握手层又包含了四个子协议。包括握手协议(hand protocol),更改加密规范协议(chage cipher spec protocol),应用数据协议(application data protocol)和警告协议(alert protocol),具体结构如下图。
在这里插入图片描述
密钥变更协议是用来通知对方从加密状态转变为非加密状态。
应用数据协议是使用商量好的密钥,加密应用数据,对数据进行打包和处理。
警报协议,告知对端通信出现异常状况,通常会携带close_notify异常,在连接关闭时使用,报告错误。其具体组成如下
struct{
AlertLevel level; //表示警告的严重程度取warning或fatal
AlertDescription description;//表示警报代码
}
严重程度为fatal的消息会立即终止当前链接并使会话失效。其中有一种警报为关闭连接警报,它用于以有序的方式关闭TLS连接。一旦一段决定关闭数据连接,就发送一个close_notify警报。在另一端收到该警报后,会丢弃任何未写出的数据。并发送自己的close_notify警报。在警报之后到来的任何消息都将被忽略。可以避免截断攻击,及时关闭协议。
最重要的就是TLS的握手协议。握手协议的详情在下文展开。

8.TLS握手协议

TLS握手协议是用来进行身份认证以及协商加密算法的。握手协议消息的标头信息包含消息类型(1字节)和长度(3字节),余下的信息则取决于消息类型。其具体过程如下。
在这里插入图片描述
我个人使用Python代码进行了一次简单的TLS握手的模拟:
客户端:

# -*- coding: utf-8 -*-
import socket
import random
import json
import rsa
import hashlib
from Crypto.Cipher import AES

# 定义服务端基本信息进行连接
host = "127.0.0.1"
port = 12345
obj = socket.socket()
obj.connect((host, port))

# Hello握手信号中所包含的内容
randNumber = random.randint(0, 100)  # 第一次生成的不重数
SSLVersion = "1.0"  # SSL版本
algorithmList = ['AES']  # 由于目前我只知道AES算法。所以列表中只是AES算法
someNeededInformation = ['NotNull', 'Space']  # 随意填充了一些必要信息
clientCertificate = "Client"  # 客户端的证书,用于服务器对客户端真实性的验证


def hello_handShake(conn):
    print("----------Start to send handshake signal----------")
    helloHandShake = {'randNumber': randNumber,
                      'SSLVersion': SSLVersion,
                      'algorithmList': algorithmList,
                      'someNeededInformation': someNeededInformation}
    conn.send(bytes(json.dumps(helloHandShake), encoding="utf-8"))
    print("----------Hello HandShake Single Send Success----------")
    return True


def recvAfterShakeHand(conn):
    # 接收服务端所发过来的证书,证书中的公钥,SSL的版本,服务端所确定的算法,
    # 服务端传送过来的消息,以及是否需要确认客户端合法性的信号
    print("----------Receive from Server Start----------")
    serverResponse = json.loads(str(conn.recv(1024), encoding="utf-8"))
    print("从服务端收到的服务端证书:" + serverResponse["certificate"])
    print("从服务端收到的SSL版本号:" + serverResponse["SSLVersion"])
    print("从服务端收到的算法列表:" + serverResponse["algorithm"])
    print("从服务端收到的消息:" + serverResponse["msg"])
    print("从服务端收到的客户端是否确认的消息:" + str(serverResponse["clientConfirm"]))
    # 如果服务器需要要求客户端的身份验证则发送客户端的身份验证
    if serverResponse['clientConfirm']:
        conn.send(bytes(clientCertificate, "utf-8"))

    serverConfirm = serverResponse['certificate']
    if serverConfirm != "Server":
        s = input("该服务端证书不可信,是否继续连接?Y/N")
        if s == 'N':
            return

    # 获取服务端的公钥
    serverPublicKey = rsa.PublicKey(serverResponse['publicKey']['n'], serverResponse['publicKey']['e'])
    print("从服务端收到的服务端的公钥:" + str(serverPublicKey))
    # 发送一个随机数
    rand = random.randint(0, 100)
    # 将此随机数用服务端的公钥加密
    msg = str(rand).encode("utf-8")
    cryptoRand = rsa.encrypt(msg, serverPublicKey)
    # 加密后的随机数的md5值
    randHashCode = hashlib.md5(cryptoRand).hexdigest()
    # 编码变更通知,表示随后的信息都将用双方商定的加密方法和密钥发送
    # 双方协定的加密算法的密钥
    publicKey = "123456"
    # 编码改变通知  注意此处publicKey经过处理后为字节流 需要解码为字符串
    codeChangeNotify = {"finalAlgorithm": serverResponse['algorithm'], "publicKey": publicKey}

    # ChangeCipherSpec是一个独立的协议,体现在数据包中就是一个字节的数据,
    # 用于告知服务端,客户端已经切换到之前协商好的加密套件(Cipher Suite)的状态,
    # 准备使用之前协商好的加密套件加密数据并传输了
    changeCiperSpec = True

    # 在ChangecipherSpec传输完毕之后,客户端会使用之前协商好的加密套件和Session Secret加密
    # 一段 Finish 的数据传送给服务端,此数据是为了在正式传输应用数据之前对刚刚握手建立起来的
    # 加解密通道进行验证。
    publicKey = addTo16(publicKey)
    aes = AES.new(publicKey, AES.MODE_ECB)
    finishInformation = "Client finish"
    finishInformation = addTo16(finishInformation)
    finishInformation = aes.encrypt(finishInformation)

    # 作者能力有限无法构造为一整个报文,因此只能先将加密后的随机数发送,然后再将其余两个值发送
    data = json.dumps({"codeChangeNotify": codeChangeNotify, "randHashCode": randHashCode,
                       "changeCiperSpec": changeCiperSpec})
    conn.send(cryptoRand)
    conn.send(bytes(data, encoding="GBK"))
    conn.send(finishInformation)
    print("----------Receive from server finish----------")
    return True


def finalRecv(conn):
    print("----------Final step of handshake start----------")
    data = json.loads(str(conn.recv(1024), encoding="utf-8"))
    print("从客户端收到的changeCipherSpec:" + str(data['changeCipherSpec']))
    print("从客户端收到的finish消息:" + str(data['finshInformation']))
    print("----------Final step of handshake end----------")


def addTo16(par):
    # 由于AES算法需要明文和密文都是16位 24位或32位字节。本次采用16位
    # 将不足16位的进行16位补足
    par = par.encode("utf-8")  # 先将字符串类型数据转换成字节型数据
    while len(par) % 16 != 0:
        par += b'\x00'
    return par


def main():
    # 客户端给服务端发送握手信号
    flg = hello_handShake(obj)
    if flg:
        # 如果握手成功,进行接收和第二次发送
        flg = recvAfterShakeHand(obj)
        if flg:
            # 如果第二次接收和发送成功,进行最后的数据接收
            finalRecv(obj)


if __name__ == '__main__':
    main()

服务端

# -*- coding: utf-8 -*-
import socket
import json
import rsa
import random
from Crypto.Cipher import AES
import hashlib

# TCP连接基本配置
host = "127.0.0.1"
port = 12345
sk = socket.socket()  # 创建一个套接字对象
sk.bind((host, port))  # 绑定地址和端口号
sk.listen(5)  # 设置最大连接数

# 服务端SSL配置
publicKey, privateKey = rsa.newkeys(1024)  # 使用RSA算法生成公钥和私钥
certificate = "Server"  # 由于不知道证书具体格式,以一个字符串代替
SSLVersion = "1.0"  # SSL协议版本
randNum = random.randint(100, 200)  # 服务端的不重数
clientConfirm = False  # 是否需要验证客户端有效性


def dealHelloAndSend(helloSignal, conn):
    if helloSignal is not None:

        print("---------The handshake signal from client----------")
        clientRandNum = helloSignal['randNumber']  # 从客户端接收到的随机数
        print("从客户端收到的随机数:" + str(clientRandNum))
        clientSSLVersion = helloSignal['SSLVersion']  # 从客户端接受到的版本号
        print("从客户端收到的版本号:" + clientSSLVersion)
        clientAlgorithmList = helloSignal['algorithmList']  # 从客户端接收到的所支持的算法列表
        print("从客户端收到的算法列表:",end=" ")
        print(clientAlgorithmList)

        if clientSSLVersion != SSLVersion:  # 协议版本不匹配则终止连接
            print("Version unknown")
            return
        needAlgorithm = clientAlgorithmList[0]  # 选定一个客户端支持的算法,
        # 因为目前只知道一个对称加密算法,只选一个
        firstReturn = json.dumps({"certificate": certificate, "publicKey": {"n": publicKey.n, "e": publicKey.e},
                                  "SSLVersion": SSLVersion, "algorithm": needAlgorithm,
                                  "msg": "Hello Done", "clientConfirm": clientConfirm})
        conn.sendall(bytes(firstReturn, encoding="utf-8"))  # 将返回内容以json字符串发送回去

        print("----------Hello Done Finish----------")
        return True


def dealNextSendAndSend(clientRandomNum, afterHandSignal, finnishInformation, conn):
    print("----------Receive from Client Start----------")

    print("从客户端收到的加密后的随机数:" + str(clientRandomNum))
    print("从客户端收到的编码改变通知:" + str(afterHandSignal['codeChangeNotify']))
    print("从客户端收到的完整性检验的hash值:" + str(afterHandSignal['randHashCode']))
    print("从客户端收到的ChangeCipherSpec值:" + str(afterHandSignal['changeCiperSpec']))
    print("从客户端收到的finish消息:" + str(finnishInformation))

    # 查看md5的值与所传过来的是否一致,验证消息完整性
    encodeMd5 = hashlib.md5(clientRandomNum).hexdigest()

    if afterHandSignal['randHashCode'] == encodeMd5:
        print("The information is complete")
        realRandNum = rsa.decrypt(clientRandomNum, privateKey).decode()
        print("The Client RandNumber is " + realRandNum)
        changeCiperSpec = afterHandSignal['changeCiperSpec']
        if changeCiperSpec == False:
            return False
        publicKey = afterHandSignal['codeChangeNotify']['publicKey']
        publicKey = addTo16(publicKey)
        if afterHandSignal['codeChangeNotify']['finalAlgorithm'] != 'AES':
            return False

        aes = AES.new(publicKey, AES.MODE_ECB)
        finnishInformation = aes.decrypt(finnishInformation).decode()
        print("The FinishInformation is " + finnishInformation)

        # 给客户端发送一个changeCipherSpec,告知加密套件准备状态
        changeCipherSpec = True
        # 给客户端以协商的加密方式发送一段finsh消息
        finshInformation = "Server finish"
        sendToCilent = {"changeCipherSpec": changeCipherSpec, "finshInformation": finshInformation}
        data = json.dumps(sendToCilent)
        conn.send(bytes(data, encoding="utf-8"))
        print("Send Finish!")
    else:
        print("The code is invalid")
        return False

    print("----------Receive from Server End----------")


def addTo16(par):
    # 由于AES算法需要明文和密文都是16位 24位或32位字节。本次采用16位
    # 将不足16位的进行16位补足
    par = par.encode("utf-8")  # 先将字符串类型数据转换成字节型数据
    while len(par) % 16 != 0:
        par += b'\x00'
    return par


def main():
    while True:
        print("The port is listening...")
        print("wait the client")  # 等待客户端连接
        conn, address = sk.accept()
        print("Connecting...")
        print("Connect from: ", address)
        helloSignal = json.loads(str(conn.recv(1024), encoding="utf-8"))
        flg = dealHelloAndSend(helloSignal, conn)
        if flg:
            if clientConfirm:  # 如果客户端验证非法,终止连接
                ret = conn.recv(1024)
                if ret != "client":
                    return
            clientRandomNum = conn.recv(1024)
            afterHandSignal = json.loads(conn.recv(1024), encoding="GBK")
            finnishInformation = conn.recv(1024)
            dealNextSendAndSend(clientRandomNum, afterHandSignal, finnishInformation, conn)
        else:
            print("SSLConnectFail")
            return


if __name__ == '__main__':
main()

客户端:
在这里插入图片描述
服务端:
在这里插入图片描述

9.TSL握手过程中的各个信号的详解

(1)Client hello
在一次新的握手流程中,ClientHello消息总是第一条消息,这条消息将客户端的功能和首选项传送给服务器。客户端会在新建连接之后,希望重新协商或者响应服务器发起的重新协商的请求(由HelloRequest消息指示)时,发送这条消息。在握手时,客户端和服务器都会提供随机数。这种随机性对每次握手都是独一无二的,在身份验证中起着重要的作用,可以防止重放攻击,并确认初始数据交换的完整性。详细结构如下图:
在这里插入图片描述
(2)Server hello
ServerHello将服务器选择的连接参数传回给客户端,消息结构与ClientHello类似。但是每个字段只包含其选中的一个选项,结构如图:
在这里插入图片描述
如果服务端所支持的版本与客户端支持的版本不一致,可以提供其他版本期待客户端能够接受。
(3)Certificate
典型的Certificate消息用于携带服务器X.509证书链,该证书链是一种格式,证书链是以ASN.1 DER编码的一系列证书,一个接一个组合而成。主证书必须第一个发送,中间证书按照正确的顺序跟在主证书之后,根证书可以并且应该省略掉,因为在这个场景中它没有用处。
服务器必须保证它发送的证书与所选择的算法套件一致。比如说,公钥算法与套件中使用的必须匹配。除此之外,一些密钥交换算法依赖嵌入证书的特定数据,而且要求证书必须以客户端支持的签名算法。所有这些都表明服务器需要配置多个证书(每个证书可能会配备不同的证书链)。
Certificate消息是可选的,因为并非所有套件都使用身份验证。也并非所有身份验证方法都需要证书。更进一步的说,虽然消息默认使用X.509证书,但是也可以携带其他形式的标志。一些套件就依赖PGP密钥。
(4)ServerKeyExchange
ServerKeyExchange消息的目的是携带密钥交换的额外数据,消息内容对于不同的协商算法套件都会存在差异,在某些场景中,服务器不需要发送任何内容,这意味着在这些场景中根本不会发送ServerKeyExchage消息。
(5)ServerHelloDone
ServerHelloDone消息表明服务器已经将所有预计的握手消息发送完毕,服务器会等待客户端消息。
(6)ClientKeyExchange
ClientKeyExchagne消息携带客户端为密钥交换提供的所有信息,这个消息受协商的密码套件影响,内容随着不同的协商密码套件而不同。
(7)ChangeCipherSpec
ChangeCipherSpec消息表明发送端已经取得用以生成连接参数的足够信息,已经生成加密密钥,并且切换到加密模式。客户端和服务器在条件成熟时都会发送这个消息。
(8)Finished
Finished消息意味着握手已经完成。消息内容将加密,以便双方可以安全地交换验证整个握手完整性所需要的数据。这个消息包verify_data字段,它的值是握手过程中所有消息的散列值,这些消息在连接两端都按照各自所见的顺序排列,并以协商新的到的主密钥计算散列值。这个过程是通过一个为随机函数(PRF)来完成的,这个函数可以生成任意数量的伪随机数据。在TLS1.2版本中,Finished消息的长度默认是12字节(96位),除了SSL3 使用36字节的定长消息,其他版本都是使用12字节的定长消息。

10.TLS短握手

一次完整的TLS握手需要发送多次信息,是一个十分耗时的操作。短握手可以通过认证Session来缩短握手的过程。短握手时,服务器为会话指定唯一的会话ID,服务器在ServerHello消息中将会话ID发送给客户端,希望恢复之前会话的客户端将会话ID放入ClientHello消息。服务器如果愿意恢复会话,就将相同的会话ID放入ServerHello消息返回,切换到加密模式,发送Finished消息。
具体步骤如下:
1.客户端恢复握手(ClientHello),将session_id加入到握手消息中
2.服务器查找该session_id,如果找到并且想要恢复会话,就将该session_id传回给客户端并切换到加密模式,通知客户端。
3.服务器计算之前发送和接收到的所有有关握手的消息,形成MAC并发送(签名)。
4.客户端切换到加密方式并通知服务器。
5.客户端计算发送和接收到的握手消息的MAC并发送。

11.对客户端和服务器都进行身份验证的握手

这种握手就是在传统的握手方式的基础上添加了服务端对客户端身份的验证。具体过程如下:
在这里插入图片描述

12.TLS密钥交换

密钥的协商和交换时TLS的一个关键。密钥交换中有两个重点的问题。一是,密钥周期尽可能要短,最好是一次会话用一个密钥。其次是密钥不能明文传输,一旦被窃听所有努力都白费。密钥的传输采用非对称加密,非对称加密的特点是公钥加密,只能用私钥解密。
非对称算法在密钥交换中的具体应用是:假设服务器拥有公钥和私钥,服务器将自己的证书以及公钥明文发送给客户端,然后客户端自己生成一个密钥,再用服务端的公钥加密这个密钥。重点是,这个加密的结果,只有私钥能解密。而私钥只在服务端,也就是说,被非对称加密的密钥只能由服务端解密。这样就完成了密钥交换。
在原来,较为广泛使用的就是上述加密过程,该加密过程主要通过RSA算法进行实现。但是RSA面临一个很大的问题就是一旦私钥外泄,那么第三方就能从之前所有加密的密钥中解密得到Key,使用Key就可以破解之前监听得到的密文。私钥参与了密钥交换,安全性也随之取决于私钥的安全性。除了RSA算法之外,还有DH,DHE,ECDHE都可以用于密钥交换。
1.DHE算法的密钥交换过程:
临时Diffie-Hellman(DHE)密钥交换是一种构造完备的算法,其优点是支持前向保密。基于的数学难题是离散对数。缺点是执行缓慢。其大致过程如下
客户端A生成一个随机数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^yx = g^yx,所以key1 = key2,密钥交换成功,而且中间没有传输客户端与服务端私有的x和y,传输的只是p,g,g^x mod p, g^y mod p,在已知这四个数的情况下是很难得出x与y的,这是依赖于离散对数这个难题。由于每次生成不同的x和y,因此之前加密的数据不会泄露。
实际上,私钥的功能被削弱到用来身份认证,实际上上文中的DHE参数和b都是通过server key exchange发送给客户端,a通过client key exchange发送给服务器,server key exchange的结尾处需要用私钥对该报文本身进行签名,来证明自己拥有私钥,证明身份。
在ECDHE密钥交换中,使用的是椭圆曲线算法,椭圆曲线(如secp256k1)和b通过server key exchange报文发送,a通过client key exchange报文发送。
2.ECDHE算法的密钥交换过程
首先ECDHE的全称是临时椭圆曲线Diffie-Hellman,它就是将DHE中模幂运算替换成了点乘运算,速度更快,破解更难。其密钥交换建立在椭圆曲线加密的基础之上,椭圆曲线算法是相对较新的算法。其流程如下:
客户端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))。
服务端B计算key2(x,y)= b * (a * Q(x,y))。
key1 = key2 = key,取key的x向量作为主密钥(预主密钥,将预主密钥通过一个方法的计算就能得到一个主密钥)
Q(x,y)为公认的某个椭圆曲线算法的基点,例如secp256k1与secp384r1这个椭圆曲线是一个事先定义好的。
3.ECDHE与RSA的区别
ECDHE(DHE)算法属于DH类密钥交换算法,私钥不参与密钥交换,即使密钥泄露,加密的报文都无法破解,实现了前向安全(forward secrity),由于ECDHE每条会话都会重新计算一个密钥(a,b),所以当一个会话被破解之后,其他会话仍是安全的。
然而,ECDH算法服务端的私钥是固定的,即证书的密钥作为b,故ECDH不被认为前向安全,因为私钥泄密相当b泄露,可以使用b计算出之前所有的密钥。
4.常用的密钥交换算法与套件
TLS中的常用算法:
rsa RSA密钥交换和身份验证。
dhe_rsa 临时DH密钥交换,使用RSA身份验证。
ecdhe_rsa 临时ECDH密钥交换,使用RSA身份验证(RFC 4492)
ecdhe_ecdsa 临时ECDH密钥交换,使用ECDSA身份验证(RFC 4492)
krb5 Kerberos密钥交换(RFC 2712)
ecdh_anno 临时椭圆曲线DH(elliptic cure DH,ECDH)密钥交换, 未经身份验证(RFC 4492)
psk 预共享密钥(pre-shared key,PSK)密钥交换和身份验证(RFC 4279)
dhe_psk 临时DH密钥交换,使用PSK身份验证(RFC 4297)
rsa_psk PSK密钥交换,使用RSA身份验证(RFC 4279)
srp 安全远程密码(secure remote password,SRP)密钥交换和身份 验证
dh_anon Diffie-Hellman(DH)密钥交换,未经身份验证。

13.TLS中的密钥套件

密钥套件是一个协议框架,TLS为实现安全属性提供了很大的灵活性,之前的TLS版本将某些加密基元编码到了协议中,但TLS1.2是完全可配置的。密码套件是一组选定的加密基元和其他参数,它可以精确定义如何实现安全。套件大致由以下属性定义。
在这里插入图片描述
本文整理了一周左右,如有不当之处,请在下方评论区指正,谢谢各位。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章