In this demonstration a client has connected to a server, negotiated a TLS 1.2 session, sent "ping", received "pong", and then terminated the session. Click below to begin exploring.
if vers == 0 {
// Some TLS servers fail if the record version is
// greater than TLS 1.0 for the initial ClientHello.
vers = VersionTLS10
}
All data following this header is the payload for this record.
$ openssl x509 -outform der < server.crt | hexdump
0000000 30 82 03 21 30 82 02 09 a0 03 02 01 02 02 08 15
0000010 5a 92 ad c2 04 8f 90 30 0d 06 09 2a 86 48 86 f7
... snip ...
909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafThe public key is chosen by multiplying the point x=9 on the x25519 curve by the private key. The public key calculated is:
9fd7ad6dcff4298dd3f96d5b1b2af910a0535b1488d7f8fabb349a982880b615The public key calculation can be confirmed with command line tools:
### requires openssl 1.1.0 or higher
$ openssl pkey -noout -text < server-ephemeral-private.key
X25519 Private-Key:
priv:
90:91:92:93:94:95:96:97:98:99:9a:9b:9c:9d:9e:
9f:a0:a1:a2:a3:a4:a5:a6:a7:a8:a9:aa:ab:ac:ad:
ae:af
pub:
9f:d7:ad:6d:cf:f4:29:8d:d3:f9:6d:5b:1b:2a:f9:
10:a0:53:5b:14:88:d7:f8:fa:bb:34:9a:98:28:80:
b6:15
### client random from Client Hello
$ echo -en '\x00\x01\x02\x03\x04\x05\x06\x07' > /tmp/compute
$ echo -en '\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f' >> /tmp/compute
$ echo -en '\x10\x11\x12\x13\x14\x15\x16\x17' >> /tmp/compute
$ echo -en '\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f' >> /tmp/compute
### server random from Server Hello
$ echo -en '\x70\x71\x72\x73\x74\x75\x76\x77' >> /tmp/compute
$ echo -en '\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f' >> /tmp/compute
$ echo -en '\x80\x81\x82\x83\x84\x85\x86\x87' >> /tmp/compute
$ echo -en '\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f' >> /tmp/compute
### the curve info section from this message
$ echo -en '\x03\x00\x1d' >> /tmp/compute
### the public key sections from this msg
$ echo -en '\x20\x9f\xd7\xad\x6d\xcf\xf4\x29' >> /tmp/compute
$ echo -en '\x8d\xd3\xf9\x6d\x5b\x1b\x2a\xf9' >> /tmp/compute
$ echo -en '\x10\xa0\x53\x5b\x14\x88\xd7\xf8' >> /tmp/compute
$ echo -en '\xfa\xbb\x34\x9a\x98\x28\x80\xb6\x15' >> /tmp/compute
$ openssl dgst -sign server.key -sha256 /tmp/compute | hexdump
0000000 04 02 b6 61 f7 c1 91 ee 59 be 45 37 66 39 bd c3
... snip ...
00000f0 7d 87 dc 33 18 64 35 71 22 6c 4d d2 c2 ac 41 fb
202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3fThe public key is chosen by multiplying the point x=9 on the x25519 curve by the private key. The public key calculated is:
358072d6365880d1aeea329adf9121383851ed21a28e3b75e965d0d2cd166254The public key calculation can be confirmed at the command line:
### requires openssl 1.1.0 or higher
$ openssl pkey -noout -text < client-ephemeral-private.key
X25519 Private-Key:
priv:
20:21:22:23:24:25:26:27:28:29:2a:2b:2c:2d:2e:
2f:30:31:32:33:34:35:36:37:38:39:3a:3b:3c:3d:
3e:3f
pub:
35:80:72:d6:36:58:80:d1:ae:ea:32:9a:df:91:21:
38:38:51:ed:21:a2:8e:3b:75:e9:65:d0:d2:cd:16:
62:54
df4a291baa1eb7cfa6934b29b474baad2697e29f1f920dcc77c8a0a088447624I've provided a tool to perform this calculation:
$ gcc -o curve25519-mult curve25519-mult.c
$ ./curve25519-mult client-ephemeral-private.key \
server-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]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 4c
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
### combine them into a single stream
$ 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 key
$ hexkey=f656d037b173ef3e11169f27231a84b6
### IV for this record
$ hexiv=404142434445464748494a4b4c4d4e4f
### encrypted data
$ echo -en '\x22\x7b\xc9\xba\x81\xef\x30\xf2' > /tmp/msg1
$ echo -en '\xa8\xa7\x8f\xf1\xdf\x50\x84\x4d' >> /tmp/msg1
$ echo -en '\x58\x04\xb7\xee\xb2\xe2\x14\xc3' >> /tmp/msg1
$ echo -en '\x2b\x68\x92\xac\xa3\xdb\x7b\x78' >> /tmp/msg1
$ echo -en '\x07\x7f\xdd\x90\x06\x7c\x51\x6b' >> /tmp/msg1
$ echo -en '\xac\xb3\xba\x90\xde\xdf\x72\x0f' >> /tmp/msg1
$ cat /tmp/msg1 | openssl enc -d -aes-128-cbc -K $hexkey -iv $hexiv | hexdump
0000000 14 00 00 0c cf 91 96 26 f1 36 0c 53 6a aa d7 3a
0000010 a5 a0 3d 23 30 56 e4 ac 6e ba 7f d9 e5 31 7f ac
0000020 2d b5 b7 0e 0b
The last 21 bytes contain a MAC and the number
of (not shown) padding bytes and can be ignored.
seed = "client finished" + SHA256(all handshake messages) a0 = seed a1 = HMAC-SHA256(key=MasterSecret, data=a0) p1 = HMAC-SHA256(key=MasterSecret, data=a1 + seed) verify_data = p1[first 12 bytes]The verify data calculated from this hash is a0744dd49a212f152b3c060d. We can show this on the command line:
### set up our MasterSecret as a hex string
$ mshex=$(hexdump -ve '/1 "%02x"' /tmp/mastersecret)
### build the seed
$ echo -en 'client finished' > /tmp/seed
### add SHA256(all_messages) to seed
$ echo -en '\x06\x1d\xda\x04\xb3\xc2\x21\x7f' >> /tmp/seed
$ echo -en '\xf7\x3b\xd7\x9b\x9c\xf8\x8a\x2b' >> /tmp/seed
$ echo -en '\xb6\xec\x50\x54\x04\xaa\xc8\x72' >> /tmp/seed
$ echo -en '\x2d\xb0\x3e\xf4\x17\xb5\x4c\xb4' >> /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
### 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
$ head -c 12 /tmp/p1 > /tmp/verify_data
$ hexdump /tmp/verify_data
0000000 cf 91 96 26 f1 36 0c 53 6a aa d7 3a
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 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]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 4c
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 b8
### server key
$ hexkey=752a18e7a9fcb7cbcdd8f98dd8f769eb
### IV for this record
$ hexiv=5152535455565758595a5b5c5d5e5f60
### encrypted data
$ echo -en '\x18\xe0\x75\x31\x7b\x10\x03\x15' > /tmp/msg1
$ echo -en '\xf6\x08\x1f\xcb\xf3\x13\x78\x1a' >> /tmp/msg1
$ echo -en '\xac\x73\xef\xe1\x9f\xe2\x5b\xa1' >> /tmp/msg1
$ echo -en '\xaf\x59\xc2\x0b\xe9\x4f\xc0\x1b' >> /tmp/msg1
$ echo -en '\xda\x2d\x68\x00\x29\x8b\x73\xa7' >> /tmp/msg1
$ echo -en '\xe8\x49\xd7\x4b\xd4\x94\xcf\x7d' >> /tmp/msg1
$ cat /tmp/msg1 | openssl enc -d -aes-128-cbc -K $hexkey -iv $hexiv | hexdump
0000000 14 00 00 0c 84 4d 3c 10 74 6d d7 22 f9 2f 0c 7e
0000010 20 c4 97 46 d2 a3 0f 23 57 39 90 58 07 53 52 43
0000020 af f2 bf e0 0b
The last 21 bytes contain a MAC and the number
of (not shown) padding bytes and can be ignored.
seed = "server finished" + SHA256(all handshake messages) a0 = seed a1 = HMAC-SHA256(key=MasterSecret, data=a0) p1 = HMAC-SHA256(key=MasterSecret, data=a1 + seed) verify_data = p1[first 12 bytes]The verify data calculated from this hash is a0744dd49a212f152b3c060d. We can show this on the command line:
### set up our MasterSecret as a hex string
$ mshex=$(hexdump -ve '/1 "%02x"' /tmp/mastersecret)
### build the seed
$ echo -en 'server finished' > /tmp/seed
### add SHA256(all_messages) to seed
$ echo -en '\xb2\x01\x7b\xa2\x8d\x0e\x27\xf0' >> /tmp/seed
$ echo -en '\x3a\xe3\x27\x45\x6b\x6f\xf0\x0b' >> /tmp/seed
$ echo -en '\x4d\x5b\xbf\x0e\xf7\xcd\xa8\x3c' >> /tmp/seed
$ echo -en '\xe1\x02\x9b\x52\x1c\x3e\x7c\x35' >> /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
### 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
$ head -c 12 /tmp/p1 > /tmp/verify_data
$ hexdump /tmp/verify_data
0000000 84 4d 3c 10 74 6d d7 22 f9 2f 0c 7e
### client key
$ hexkey=f656d037b173ef3e11169f27231a84b6
### IV for this record
$ hexiv=000102030405060708090a0b0c0d0e0f
### encrypted data
$ echo -en '\x6c\x42\x1c\x71\xc4\x2b\x18\x3b' > /tmp/msg1
$ echo -en '\xfa\x06\x19\x5d\x13\x3d\x0a\x09' >> /tmp/msg1
$ echo -en '\xd0\x0f\xc7\xcb\x4e\x0f\x5d\x1c' >> /tmp/msg1
$ echo -en '\xda\x59\xd1\x47\xec\x79\x0c\x99' >> /tmp/msg1
$ cat /tmp/msg1 | openssl enc -d -aes-128-cbc -K $hexkey -iv $hexiv | hexdump
0000000 70 69 6e 67 60 10 12 49 f7 4a 03 77 c9 ca cf 63
0000010 09 75 13 70 d8 0c fc aa 07
The last 21 bytes contain a MAC and the number
of (not shown) padding bytes and can be ignored.
### server key
$ hexkey=752a18e7a9fcb7cbcdd8f98dd8f769eb
### IV for this record
$ hexiv=6162636465666768696a6b6c6d6e6f70
### encrypted data
$ echo -en '\x97\x83\x48\x8a\xf5\xfa\x20\xbf' > /tmp/msg1
$ echo -en '\x7a\x2e\xf6\x9d\xeb\xb5\x34\xdb' >> /tmp/msg1
$ echo -en '\x9f\xb0\x7a\x8c\x27\x21\xde\xe5' >> /tmp/msg1
$ echo -en '\x40\x9f\x77\xaf\x0c\x3d\xde\x56' >> /tmp/msg1
$ cat /tmp/msg1 | openssl enc -d -aes-128-cbc -K $hexkey -iv $hexiv | hexdump
0000000 70 6f 6e 67 5a c7 99 dc cf dc 0f af 95 2b dc 91
0000010 18 af 20 0e e3 1c 51 05 07
The last 21 bytes contain a MAC and the number
of (not shown) padding bytes and can be ignored.
### client key
$ hexkey=f656d037b173ef3e11169f27231a84b6
### IV for this record
$ hexiv=101112131415161718191a1b1c1d1e1f
### encrypted data
$ echo -en '\x0d\x83\xf9\x79\x04\x75\x0d\xd8' > /tmp/msg1
$ echo -en '\xfd\x8a\xa1\x30\x21\x86\x32\x63' >> /tmp/msg1
$ echo -en '\x4f\xd0\x65\xe4\x62\x83\x79\xb8' >> /tmp/msg1
$ echo -en '\x8b\xbf\x9e\xfd\x12\x87\xa6\x2d' >> /tmp/msg1
$ cat /tmp/msg1 | openssl enc -d -aes-128-cbc -K $hexkey -iv $hexiv | hexdump
0000000 01 00 92 79 9c ba 81 9f 31 07 44 c5 59 62 2b e4
0000010 2b ce 3d 6a 41 fb 09
The last 21 bytes contain a MAC and the number
of (not shown) padding bytes and can be ignored.
The code for this project can be found on GitHub.
If you found this page useful or interesting let me know via Twitter @XargsNotBombs.