Last active
January 27, 2022 22:36
-
-
Save Oldes/2a59274d737feaf47c3fedbeb17ab594 to your computer and use it in GitHub Desktop.
TLS with ChaCha20-Poly1305 use-case simulation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Rebol [ | |
title: "TLS with ChaCha20-Poly1305 use-case simulation" | |
needs: 3.8.0 | |
] | |
print "--------------------------------------------------" | |
print "- TLS with ChaCha20-Poly1305 use-case simulation -" | |
print "--------------------------------------------------" | |
;- server and client exchange it's keys and initialization vectors | |
;; (how it is exchanged may be described later) | |
server-key: #{AE8A57A15387FD92E9DAA50FECD6CA31044A7EEC9459EC9C6ED6A93EE4F6CC42} | |
client-key: #{438D7027FD611C1A5CD532D1151665EA3BB925CF1F37453C109790B604E7A0C4} | |
server-IV: #{F01A5EF18B11C15FB97AE808} | |
client-IV: #{9F45E14C213A3719186DDF50} | |
;- client sends data encrypted using own key and IV | |
client-out: open [ | |
scheme: 'crypt | |
algorithm: 'CHACHA20-POLY1305 | |
key: :client-key | |
init-vector: :client-iv | |
] | |
;; first ChaCha20-Poly1305 write must be AAD chunk | |
;; AAD structure used in TLS protocol: | |
;; 8 bytes - sequence ID (starting from 0) | |
;; 1 byte - sequence type | |
;; 2 bytes - TLS version | |
;; 2 bytes - length of data | |
;; AAD is internally padded to 16 bytes with zeros | |
;; As it is first data message, the sequence ID is 0 | |
;; The sequence type 0x16 is for HANDSHAKE protocol message | |
write client-out #{0000000000000000 16 0303 0010} | |
;: second write is the client's handshake message | |
write client-out client-data: #{1400000C89F6A49D54518857D140BE74} | |
;: to get finished encrypted message, we must first call update on the crypt port | |
update client-out | |
;; and than read encrypted result | |
result: read client-out | |
;; result ends with 16 bytes of MAC used as message authentication | |
expect: #{AE84B0499E0B7837027C6FD712A68894 EBF068BE0FFF3A36419EEB804A5651F5} | |
print as-yellow "^/Client sends encrypted result with the MAC at tail to server..." | |
? result | |
? expect | |
;- on the server side, server decrypts the message using client's key and IV | |
server-inp: open [ | |
scheme: 'crypt | |
direction: 'decrypt | |
algorithm: 'CHACHA20-POLY1305 | |
key: :client-key | |
init-vector: :client-iv | |
] | |
;; server must first separate the message and the MAC | |
mac1: take/last/part result 16 | |
;; first write is again AAD, same as client used (it's part of the TLS protocol) | |
write server-inp #{0000000000000000 16 0303 0010} | |
;; second write is the encrypted message | |
write server-inp result | |
;; again we need to update and read... now in a shorter way | |
result: read update server-inp result | |
;; removes the MAC from the tail | |
mac2: take/last/part result 16 | |
;; and checks, if these are equal | |
if not equal? mac1 mac2 [ print as-red "Validation failed!" ] | |
;; and should have decrypted data | |
expect: :client-data | |
print as-yellow "^/Server decrypted client message..." | |
? result | |
? expect | |
;- to answer back to client, server wants to send a response message | |
server-data: #{1400000C107581DB64B051DA4C250603} | |
;- using output crypt port with own key and IV | |
server-out: open [ | |
scheme: 'crypt | |
algorithm: 'CHACHA20-POLY1305 | |
key: :server-key | |
init-vector: :server-iv | |
] | |
;; first AAD again.. with sequence 0 (first server's message) | |
write server-out #{0000000000000000 16 0303 0010} | |
;; and data... using cryptic shorter variant | |
result: read update write server-out server-data | |
expect: #{291EC39A1BAD9E855CA8EB042014C4AFE02148981D1B3AAF137081C1901D7ED1} | |
print as-yellow "^/Server sends encrypted response with the MAC at tail to client..." | |
? result | |
? expect | |
print as-yellow "^/Client decrypts first server's response..." | |
;- client decrypts it using server's key and IV | |
client-inp: open [ | |
scheme: 'crypt | |
direction: 'decrypt | |
algorithm: 'CHACHA20-POLY1305 | |
key: :server-key | |
init-vector: :server-iv | |
] | |
mac1: take/last/part result 16 | |
write client-inp #{0000000000000000 16 0303 0010} | |
result: read update write client-inp result | |
mac2: take/last/part result 16 | |
if not equal? mac1 mac2 [ print as-red "Validation failed!" ] | |
expect: :server-data | |
? result | |
? expect | |
print as-yellow "^/Server sends real HTTP response..." | |
server-data: to binary! {HTTP/1.1 200 OK^M | |
Content-length: 31^M | |
Content-type: text/plain^M | |
^M | |
Hello world from TLSe (TLS 1.2)} | |
;; first AAD again.. with sequence 1 (second server's message) | |
;; the 0x17 is for APPLICATION protocol | |
write server-out #{0000000000000001 17 0303 0010} | |
;; and data... | |
result: read update write server-out server-data | |
expect: #{ | |
754A97C624E9316F182A8AEE4C7E89A14FDA7026F75FD1619768ACDAB6CB6226 | |
8C852C81371F6572993EFE9F9AB6800F653AA2D35670EE4DFCDDC1AA59AB6802 | |
D270E3A44EDE743AB563645E6CE6C4DD59BF7D19E15CBDF39453BBFBFFD3CFF6 | |
F040B7BCC9ECE87C31C17E858F6D0E5D | |
} | |
print as-yellow "^/Server sends encrypted response with the MAC at tail to client..." | |
? result | |
? expect | |
print as-yellow "^/Client decrypts real HTTP response..." | |
;- client decrypts it using server's key and IV | |
mac1: take/last/part result 16 | |
write client-inp #{0000000000000001 17 0303 0010} | |
result: read update write client-inp result | |
mac2: take/last/part result 16 | |
if not equal? mac1 mac2 [ print as-red "Validation failed!" ] | |
page-content: to string! result | |
?? page-content | |
;@@ here should be some closing sequence, where client notifies, that is done | |
close client-inp | |
close client-out | |
close server-inp | |
close server-out |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The output of the script (for the 2nd revision) should be: