" name="top" slick-uniqueid="4">
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.
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:
1 2 3 4 5 6
struct {
select (KeyExchangeAlgorithm) {
case rsa: EncryptedPreMasterSecret;
case diffie_hellman: ClientDiffieHellmanPublic;
} exchange_keys;
} ClientKeyExchange;
Structure of the RSA message:
1 2 3 4 5 6 7
struct {
ProtocolVersion client_version;
opaque random[46];
} PreMasterSecret;
struct {
public-key-encrypted PreMasterSecret pre_master_secret;
} EncryptedPreMasterSecret;
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.
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:
1 2 3 4 5 6 7
enum { implicit, explicit } PublicValueEncoding;
struct {
select (PublicValueEncoding) {
case implicit: struct { };
case explicit: opaque dh_Yc<1..2^16-1>;
} dh_public;
} ClientDiffieHellmanPublic;