Server Handshake Keys Calc

client public key (from Client Hello)

server private key (from Server Key Exchange Generation)

SHA256 hash of ClientHello and ServerHello

df4a291baa1eb7cfa6934b29b474baad2697e29f1f920dcc77c8a0a088447624

$ cc -o curve25519-mult curve25519-mult.c $ ./curve25519-mult server-ephemeral-private.key \ client-ephemeral-public.key | hexdump 0000000 df 4a 29 1b aa 1e b7 cf a6 93 4b 29 b4 74 ba ad 0000010 26 97 e2 9f 1f 92 0d cc 77 c8 a0 a0 88 44 76 24

da75ce1139ac80dae4044da932350cf65c97ccc9e33f1e6f7d2d4b18b736ffd5

early_secret = HKDF-Extract( salt=00, key=00...) empty_hash = SHA256("") derived_secret = HKDF-Expand-Label( key = early_secret, label = "derived", context = empty_hash, len = 32) handshake_secret = HKDF-Extract( salt = derived_secret, key = shared_secret) client_handshake_traffic_secret = HKDF-Expand-Label( key = handshake_secret, label = "c hs traffic", context = hello_hash, len = 32) server_handshake_traffic_secret = HKDF-Expand-Label( key = handshake_secret, label = "s hs traffic", context = hello_hash, len = 32) client_handshake_key = HKDF-Expand-Label( key = client_handshake_traffic_secret, label = "key", context = "", len = 16) server_handshake_key = HKDF-Expand-Label( key = server_handshake_traffic_secret, label = "key", context = "", len = 16) client_handshake_iv = HKDF-Expand-Label( key = client_handshake_traffic_secret, label = "iv", context = "", len = 12) server_handshake_iv = HKDF-Expand-Label( key = server_handshake_traffic_secret, label = "iv", context = "", len = 12)

HKDF-Extract - given a salt and some bytes of key material create 256 bits (32 bytes) of new key material, with the input key material's entropy evenly distributed in the output.

- given a salt and some bytes of key material create 256 bits (32 bytes) of new key material, with the input key material's entropy evenly distributed in the output. HKDF-Expand-Label - given the inputs of key material, label, and context data, create a new key of the requested length.

$ hello_hash=da75ce1139ac80dae4044da932350cf65c97ccc9e33f1e6f7d2d4b18b736ffd5 $ shared_secret=df4a291baa1eb7cfa6934b29b474baad2697e29f1f920dcc77c8a0a088447624 $ zero_key=0000000000000000000000000000000000000000000000000000000000000000 $ early_secret=$(./hkdf extract 00 $zero_key) $ empty_hash=$(openssl sha256 < /dev/null | sed -e 's/.* //') $ derived_secret=$(./hkdf expandlabel $early_secret "derived" $empty_hash 32) $ handshake_secret=$(./hkdf extract $derived_secret $shared_secret) $ csecret=$(./hkdf expandlabel $handshake_secret "c hs traffic" $hello_hash 32) $ ssecret=$(./hkdf expandlabel $handshake_secret "s hs traffic" $hello_hash 32) $ client_handshake_key=$(./hkdf expandlabel $csecret "key" "" 16) $ server_handshake_key=$(./hkdf expandlabel $ssecret "key" "" 16) $ client_handshake_iv=$(./hkdf expandlabel $csecret "iv" "" 12) $ server_handshake_iv=$(./hkdf expandlabel $ssecret "iv" "" 12) $ echo ckey: $client_handshake_key $ echo skey: $server_handshake_key $ echo civ: $client_handshake_iv $ echo siv: $server_handshake_iv ckey: 7154f314e6be7dc008df2c832baa1d39 skey: 844780a7acad9f980fa25c114e43402a civ: 71abc2cae4c699d47c600268 siv: 4c042ddc120a38d1417fc815

handshake secret: fb9fc80689b3a5d02c33243bf69a1b1b20705588a794304a6e7120155edf149a

client handshake traffic secret: ff0e5b965291c608c1e8cd267eefc0afcc5e98a2786373f0db47b04786d72aea .

. server handshake traffic secret: a2067265e7f0652a923d5d72ab0467c46132eeb968b6a32d311c805868548814 .

. client handshake key: 7154f314e6be7dc008df2c832baa1d39

server handshake key: 844780a7acad9f980fa25c114e43402a

client handshake IV: 71abc2cae4c699d47c600268

server handshake IV: 4c042ddc120a38d1417fc815

The server now has the information to calculate the keys used to encrypt the rest of the handshake. It uses the following information in this calculation:First, the server finds the shared secret, which is the result of the key exchange that allows the client and server to agree on a number. The server multiplies the client's public key with the server's private key using the curve25519() algorithm. The 32-byte result is found to be:I've provided a tool to perform this calculation:We then calculate the SHA256 hash of all handshake messages to this point (ClientHello and ServerHello). The hash does not include the 5-byte "record" headers. This "hello_hash" isWe then feed the hash and the shared secret into a set of key derivation operations, designed to ensure the integrity of the handshake process and to protect against known and possible attacks:This has introduced two new cryptographic methods:I've created an HKDF tool to perform these operations on the command line.From this we get the following key data: