TLS 中使用的 Premaster secret 是如何生成的?

信息安全 加密 tls RSA 客户端
2021-09-08 07:35:32

我相信它使用了 hello 消息中发送的随机值的某种组合。来自 RFC 2246:(TLSv1.0)

 RSA encrypted premaster secret message

   Meaning of this message:
       If RSA is being used for key agreement and authentication, the
       client generates a 48-byte premaster secret, encrypts it using
       the public key from the server's certificate or the temporary RSA
       key provided in a server key exchange message, and sends the
       result in an encrypted premaster secret message. This structure
       is a variant of the client key exchange message, not a message in
       itself.

   Structure of this message:
       struct {
           ProtocolVersion client_version;
           opaque random[46];
       } PreMasterSecret;

       client_version
           The latest (newest) version supported by the client. This is
           used to detect version roll-back attacks. Upon receiving the
           premaster secret, the server should check that this value
           matches the value transmitted by the client in the client
           hello message.

       random
           46 securely-generated random bytes.

它将如何匹配客户端先前发送的值?有人可以解释一下吗?谢谢你!是否有任何 API 可以计算此值?

2个回答

客户端通过连接协议版本(2 个字节)和客户端随机生成的一些字节(46 个字节)来生成 48 字节的 premaster secret。客户端应该从加密安全的 PRNG中获取这 46 个字节;实际上,这意味着使用操作系统提供的 PRNG ( /dev/urandom, CryptGenRandom()...)。

然后,客户端使用服务器的 RSA 公钥(服务器先前在Certificate消息中发送给客户端的密钥)加密 48 字节的预主密钥。加密的结果是客户端作为ClientKeyExchange消息发送到服务器的内容。由于 RSA 是一种健全的非对称加密算法,服务器解密的内容与客户端加密的内容相同。

服务器ClientKeyExchange使用其私有 RSA 密钥解密消息的内容。此时,客户端和服务器都知道预主密钥。然后他们继续使用它来计算主密钥(使用client_randomand server_random,之前在ClientHelloandServerHello消息中交换,并将整体与 PRF 混合)。从主密钥中,他们将再次使用一些 PRF 混合来获得后续数据的实际加密密钥。

TLS 支持多种密钥交换方案,因此可以有不同的方式来获取预主密钥。TLS 可以使用基于 RSA 的密钥交换,这在之前的评论中已经得到很好的解释,它还可以使用 DH、DHE、ECDH、ECDHE(diffie-hellman、diffie-hellman 和临时密钥、椭圆曲线 diffie-hellman 和 ecdh 和临时密钥分别)。

在 DH 系列算法中,预主密钥由两组值生成:

  1. 服务器选择的公共原语
  2. 发送方和接收方的私钥

服务器共享客户端使用的公共原语及其私钥,以提供预主密钥。在 Diffie Hellman 的情况下,它是这样的:

公共原语

p - a large prime 

g - primitive root modulo p 

私钥:

a - client's private key

b - server's private key

密钥交换:

Server to Client  :  {g, p, (g^b mod p)}

Client Calculates :  (g^b mod p)^a = g^ab mod p

Client to Server  :  (g^a mod p)

Server Calculates :  (g^a mod p)^b = g^ab mod p

如果你仔细看,服务器和客户端现在都有一个公共密钥 (g^ab mod p),它们可以用作预主密钥。

可以将此预主密钥提供给HKDF以提取多个加密安全密钥。然后这些密钥可以用作会话加密密钥、hmac 密钥(或基于加密密码的 IV)。

椭圆曲线 DH 不使用 p 和 g 等基元,而是使用命名的椭圆曲线。

对于你的另一个问题,

是否有任何 API 可以计算此值?

如果您的意思是加密安全的随机值,那么是的,python 有 os.urandom(n)

可用于生成 n 字节加密。安全随机值。