ClientKeyExchange describes a Step within the TLS Handshake process.
ClientKeyExchange has been removed in TLS 1.3

The ClientKeyExchange is sent by the User-agent immediately after the CertificateRequest if it was sent or otherwise immediately after the ServerHelloDone message. ClientKeyExchange has two variants, one for when RSA is used as the Key-Exchange algorithm, and one for when Diffie-Hellman is used.

This information is based on TLS 1.0

The Key-Exchange choice is part of the Cipher Suites defined for TLS.

The goal of the ClientKeyExchange is to perform a Key-Exchange of the premaster Secret so each side can independently Derive the Master Secret.

The ClientKeyExchange handshake header is not encrypted.

Structure of the ClientKeyExchange message:

struct {
    select (KeyExchangeAlgorithm) {
        case rsa: EncryptedPreMasterSecret;
        case diffie_hellman: ClientDiffieHellmanPublic;
    } exchange_keys;
} ClientKeyExchange;


If RSA is being used for key-Exchange and authentication, the user-agent generates a 48-byte premaster Secret, encrypts it using the public Key from the certificate sent in the serverCertificate message or the temporary RSA key provided in a ServerKeyExchange message, and sends the result in an encrypted premaster secret message. This structure is a variant of the ClientKeyExchange message, not a message in itself.

Structure of the RSA message:

struct {
    ProtocolVersion client_version;
    opaque random[46];
} PreMasterSecret;
struct {
    public-key-encrypted PreMasterSecret pre_master_secret;
} EncryptedPreMasterSecret;
Where the client_version is the latest (newest) version supported by the user-agent and is intended to prevent version roll-back by a Man-In-The-Middle attack. Upon receiving the premaster secret from the user-agent, the server should check that this value matches the value transmitted by the user-agent in the clientHello message. While this may indeed work for TLS but in SSLv3 implementations use of the negotiated version is common and thus checking this value creates incompatibility problems.

The random is 46 random bytes generated by a cryptographic Pseudorandom number generator which is specified within RFC 2246.

Combined these 48 bytes provide the User-agent’s input into the Master Secret from which the session keys will be derived.

The PKCS encoding is needed to pad the ClientKeyExchange to the length of the RSA key. The ClientKeyExchange consists of 0x00, 0x02, randomly generated pad bytes, 0x00 and finally the message, in our example, the ClientKeyExchange. The number of pad bytes is chosen to make the resulting message the same length as the key. The number of pad bytes must be at least 8, so the minimum pad length is 11 bytes.

In theory fragmentation of the message may be necessary, but in practice RSA keys are longer than 59 bytes – the length of the ClientKeyExchange secret combined with the minimum pad – so this is not done.

As the ClientKeyExchange message is encrypted with the server’s Public Key, only the holder of the Private Key can decrypt the message. This means that although the certificate may be sent by any party, only servers that hold the Private Key can successfully complete this part of the handshake. This also protects the version number from a Man-In-The-Middle attack, as the random bytes cannot be recovered from the message for inclusion in a modified message, and if they do not match the key material will not match on both sides and the handshake will fail when when the finished messages are processed. However as discussed above, this protection is largely useless for SSLv3.


When Diffie-Hellman is used the client Key-Exchange message consists of the handshake header followed by the Diffie-Hellman public value. This allows both the client and server to calculate the same Premaster Secret.

In the case where client authentication is used, and the client certificate that was sent, in the CertificateRequest message, contains a Diffie-Hellman public value that uses the parameters specified by the server, then the public value is omitted from this message as it is already known. In this case the handshake header comprises the message entirely.

Structure of the Diffie-Hellman part of message:

enum { implicit, explicit } PublicValueEncoding;
struct {
    select (PublicValueEncoding) {
        case implicit: struct { };
        case explicit: opaque dh_Yc<1..2^16-1>;
     } dh_public;
} ClientDiffieHellmanPublic;
  • dh_Yc - The client's Diffie-Hellman public value (Yc).
  • implicit - If the client certificate already contains a suitable Diffie-Hellman key, then Yc is implicit and does not need to be sent again. In this case, the ClientKeyExchange message will be sent, but will be empty.
  • explicit - Yc needs to be sent.

More Information#

There might be more information for this subject on one of the following: