10

I believe that it uses some combination of the random values sent in the hello messages. From 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.

How will it match the value the client sent previously? Can someone please explain this? Thank yuou! Is there any API to compute this value?

2 Answers2

20

The client generates the 48-byte premaster secret by concatenating the protocol version (2 bytes) and some bytes that the client generates randomly (46 bytes). The client is supposed to get these 46 bytes from a cryptographically secure PRNG; in practice, this means using the PRNG offered by the operating system (/dev/urandom, CryptGenRandom()...).

The client then encrypts the 48-byte premaster secret with the server's RSA public key (that the server sent previously to the client, in the Certificate message). The encrypted result is what the client sends to the server as the ClientKeyExchange message. By virtue of RSA being, well, a sound asymmetric encryption algorithm, what the server decrypts is equal to what the client encrypted.

The server decrypts the contents of the ClientKeyExchange message using its private RSA key. At that point, both client and server know the premaster secret. They then proceed to use it to compute the master secret (using the client_random and server_random, exchanged previously in the ClientHello and ServerHello messages, and mixing the whole with the PRF). From the master secret, they again will use some PRF mixing to obtain the actual encryption keys for subsequent data.

Tom Leek
  • 168,808
  • 28
  • 337
  • 475
  • 2
    Why bother generating a master key? why not just use the pre-master key for the encryption? – Kennet Celeste Sep 26 '21 at 01:10
  • There are many keys for various purposes, not just 1 encryption. Need a master key to deriver keys for those encryptions. Premaster secrets can have different formats (lengths), depends on cipher suite, but master key format is fixed. Just an extendable crypto design. Say later we may have tlsv1.4,... no much change in the design – Bao HQ Jan 15 '22 at 05:59
8

TLS supports multiple key exchange schemes and hence there can be different ways of deriving a pre master secret. TLS can use RSA based key exchange which has been pretty well explained in previous comment, it can also use DH, DHE, ECDH, ECDHE (diffie-hellman, diffie-hellman with ephemeral keys, elliptic curve diffie-hellman and ecdh with ephemeral keys respectively).

In DH family of algorithms the premaster secret is generated from two groups of values:

  1. Public primitives chosen by the server
  2. Private keys of the sender and receiver

The server shares the public primitives which the client uses along with it's private key to come up with a pre-master secret. In case of Diffie Hellman it's something like this:

Public primitives:

p - a large prime 

g - primitive root modulo p 

Private keys:

a - client's private key

b - server's private key

Key exchange:

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

If you see carefully, both the server and client now have a common key (g^ab mod p) which they can use as a pre master secret.

This pre master secret can be fed to a HKDF to extract multiple cryptographically secure keys. These keys may then be used as session encryption keys, hmac keys ( or IVs based on the encryption cipher).

Elliptic Curve DH instead of using primitives like p and g, uses named elliptic curves.

For your other question,

Is there any API to compute this value?

If you meant a cryptographically secure random value, then yes, python has os.urandom(n)

which can be used to generate an n bytes crypto. secure random value.

harshc
  • 131
  • 1
  • 4