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:
- server random (from Server Hello)
- client random (from Client Hello)
- client public key (from Client Key Exchange)
- server private key (from Server Key Generation)
The server multiplies the client's public key by the server's private key using the curve25519() algorithm. The 32-byte result is called the PreMasterSecret, and is found to be:
df4a291baa1eb7cfa6934b29b474baad2697e29f1f920dcc77c8a0a088447624I've provided a tool to perform this calculation:
$ 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 24This 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:
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]Here we demonstrate on the command line:
### 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 4cThis gives us a MasterSecret of:
916abf9da55973e13614ae0a3f5d3f37b023ba129aee02cc9134338127cd7049781c8e19fc1eb2a7387ac06ae237344cWe then generate the final encryption keys using a key expansion:
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]We can demonstrate this on the command line:
### 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 b8From this we get the following key data:
- client MAC key: 1b7d117c7d5f690bc263cae8ef60af0f1878acc2
- server MAC key: 2ad8bdd8c601a617126f63540eb20906f781fad2
- client write key: f656d037b173ef3e11169f27231a84b6
- server write key: 752a18e7a9fcb7cbcdd8f98dd8f769eb
- client write IV: a0d2550c9238eebfef5c32251abb67d6
- server write IV: 434528db4937d540d393135e06a11bb8
.png)
![AI algorithms is making all products look the same (2021) [video]](https://www.youtube.com/img/desktop/supported_browsers/opera.png)
