How is the Premaster secret used in TLS generated?
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.
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:
- Public primitives chosen by the server
- 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.