Server Encryption Keys Calculation

server random (from Server Hello)

client random (from Client Hello)

client public key (from Client Key Exchange)

server private key (from Server Key Generation)

df4a291baa1eb7cfa6934b29b474baad2697e29f1f920dcc77c8a0a088447624

$ gcc -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

seed = "master secret" + client_random + server_random a0 = seed a1 = HMAC-SHA256(key=PreMasterSecret, data=a0) a2 = HMAC-SHA256(key=PreMasterSecret, data=a1) p1 = HMAC-SHA256(key=PreMasterSecret, data=a1 + seed) p2 = HMAC-SHA256(key=PreMasterSecret, data=a2 + seed) MasterSecret = p1[all 32 bytes] + p2[first 16 bytes]

### set up our PreMasterSecret as a hex string $ pmshex=df4a291baa1eb7cfa6934b29b474baad $ pmshex=${pmshex}2697e29f1f920dcc77c8a0a088447624 ### client random from Client Hello $ echo -en '\x00\x01\x02\x03\x04\x05\x06\x07' > /tmp/c_rand $ echo -en '\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f' >> /tmp/c_rand $ echo -en '\x10\x11\x12\x13\x14\x15\x16\x17' >> /tmp/c_rand $ echo -en '\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f' >> /tmp/c_rand ### server random from Server Hello $ echo -en '\x70\x71\x72\x73\x74\x75\x76\x77' > /tmp/s_rand $ echo -en '\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f' >> /tmp/s_rand $ echo -en '\x80\x81\x82\x83\x84\x85\x86\x87' >> /tmp/s_rand $ echo -en '\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f' >> /tmp/s_rand ### build the seed $ echo -en 'master secret' > /tmp/seed $ cat /tmp/c_rand /tmp/s_rand >> /tmp/seed ### a0 is the same as the seed $ cat /tmp/seed > /tmp/a0 ### a(n) is hmac-sha256(key=secret, data=a(n-1)) $ cat /tmp/a0 | openssl dgst -sha256 \ -mac HMAC -macopt hexkey:$pmshex -binary > /tmp/a1 $ cat /tmp/a1 | openssl dgst -sha256 \ -mac HMAC -macopt hexkey:$pmshex -binary > /tmp/a2 ### p(n) is hmac-sha256(key=secret, data=a(n)+seed) $ cat /tmp/a1 /tmp/seed | openssl dgst -sha256 \ -mac HMAC -macopt hexkey:$pmshex -binary > /tmp/p1 $ cat /tmp/a2 /tmp/seed | openssl dgst -sha256 \ -mac HMAC -macopt hexkey:$pmshex -binary > /tmp/p2 ### first 48 bytes is MasterSecret $ cat /tmp/p1 /tmp/p2 | head -c 48 > /tmp/mastersecret $ hexdump /tmp/mastersecret 0000000 91 6a bf 9d a5 59 73 e1 36 14 ae 0a 3f 5d 3f 37 0000010 b0 23 ba 12 9a ee 02 cc 91 34 33 81 27 cd 70 49 0000020 78 1c 8e 19 fc 1e b2 a7 38 7a c0 6a e2 37 34 4c

916abf9da55973e13614ae0a3f5d3f37b023ba129aee02cc9134338127cd7049781c8e19fc1eb2a7387ac06ae237344c

seed = "key expansion" + server_random + client_random a0 = seed a1 = HMAC-SHA256(key=MasterSecret, data=a0) a2 = HMAC-SHA256(key=MasterSecret, data=a1) a3 = HMAC-SHA256(key=MasterSecret, data=a2) a4 = ... p1 = HMAC-SHA256(key=MasterSecret, data=a1 + seed) p2 = HMAC-SHA256(key=MasterSecret, data=a2 + seed) p3 = HMAC-SHA256(key=MasterSecret, data=a3 + seed) p4 = ... p = p1 + p2 + p3 + p4 ... client write mac key = [first 20 bytes of p] server write mac key = [next 20 bytes of p] client write key = [next 16 bytes of p] server write key = [next 16 bytes of p] client write IV = [next 16 bytes of p] server write IV = [next 16 bytes of p]

### continued from above command line example ### set up our MasterSecret as a hex string $ mshex=$(hexdump -ve '/1 "%02x"' /tmp/mastersecret) ### build the seed $ echo -en 'key expansion' > /tmp/seed $ cat /tmp/s_rand /tmp/c_rand >> /tmp/seed ### a0 is the same as the seed $ cat /tmp/seed > /tmp/a0 ### a(n) is hmac-sha256(key=secret, data=a(n-1)) $ cat /tmp/a0 | openssl dgst -sha256 \ -mac HMAC -macopt hexkey:$mshex -binary > /tmp/a1 $ cat /tmp/a1 | openssl dgst -sha256 \ -mac HMAC -macopt hexkey:$mshex -binary > /tmp/a2 $ cat /tmp/a2 | openssl dgst -sha256 \ -mac HMAC -macopt hexkey:$mshex -binary > /tmp/a3 $ cat /tmp/a3 | openssl dgst -sha256 \ -mac HMAC -macopt hexkey:$mshex -binary > /tmp/a4 ### p(n) is hmac-sha256(key=secret, data=a(n)+seed) $ cat /tmp/a1 /tmp/seed | openssl dgst -sha256 \ -mac HMAC -macopt hexkey:$mshex -binary > /tmp/p1 $ cat /tmp/a2 /tmp/seed | openssl dgst -sha256 \ -mac HMAC -macopt hexkey:$mshex -binary > /tmp/p2 $ cat /tmp/a3 /tmp/seed | openssl dgst -sha256 \ -mac HMAC -macopt hexkey:$mshex -binary > /tmp/p3 $ cat /tmp/a4 /tmp/seed | openssl dgst -sha256 \ -mac HMAC -macopt hexkey:$mshex -binary > /tmp/p4 $ cat /tmp/p1 /tmp/p2 /tmp/p3 /tmp/p4 > /tmp/p $ dd if=/tmp/p of=/tmp/client_mac_key bs=1 skip=0 count=20 $ dd if=/tmp/p of=/tmp/server_mac_key bs=1 skip=20 count=20 $ dd if=/tmp/p of=/tmp/client_key bs=1 skip=40 count=16 $ dd if=/tmp/p of=/tmp/server_key bs=1 skip=56 count=16 $ dd if=/tmp/p of=/tmp/client_iv bs=1 skip=72 count=16 $ dd if=/tmp/p of=/tmp/server_iv bs=1 skip=88 count=16 $ hexdump /tmp/client_mac_key 0000000 1b 7d 11 7c 7d 5f 69 0b c2 63 ca e8 ef 60 af 0f 0000010 18 78 ac c2 $ hexdump /tmp/server_mac_key 0000000 2a d8 bd d8 c6 01 a6 17 12 6f 63 54 0e b2 09 06 0000010 f7 81 fa d2 $ hexdump /tmp/client_key 0000000 f6 56 d0 37 b1 73 ef 3e 11 16 9f 27 23 1a 84 b6 $ hexdump /tmp/server_key 0000000 75 2a 18 e7 a9 fc b7 cb cd d8 f9 8d d8 f7 69 eb $ hexdump /tmp/client_iv 0000000 a0 d2 55 0c 92 38 ee bf ef 5c 32 25 1a bb 67 d6 $ hexdump /tmp/server_iv 0000000 43 45 28 db 49 37 d5 40 d3 93 13 5e 06 a1 1b b8

client MAC key: 1b7d117c7d5f690bc263cae8ef60af0f1878acc2

server MAC key: 2ad8bdd8c601a617126f63540eb20906f781fad2

client write key: f656d037b173ef3e11169f27231a84b6

server write key: 752a18e7a9fcb7cbcdd8f98dd8f769eb

client write IV: a0d2550c9238eebfef5c32251abb67d6

server write IV: 434528db4937d540d393135e06a11bb8

The server now has the information to calculate the encryption keys that will be used by each side. It uses the following information in this calculation:The server multiplies the client's public key with the server's private key using the curve25519() algorithm. The 32-byte result is called the PreMasterSecret, and is found to be:I've provided a tool to perform this calculation:This is identical to the PreMasterSecret found by the client, therefore the following calculations will be identical.The server then calculates 48 bytes of the MasterSecret from the PreMasterSecret using the following method:Here we demonstrate on the command line:This gives us a MasterSecret of:We then generate the final encryption keys using a key expansion:We can demonstrate this on the command line:From this we get the following key data: