Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@Oldes
Last active January 27, 2022 22:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Oldes/2a59274d737feaf47c3fedbeb17ab594 to your computer and use it in GitHub Desktop.
Save Oldes/2a59274d737feaf47c3fedbeb17ab594 to your computer and use it in GitHub Desktop.
TLS with ChaCha20-Poly1305 use-case simulation
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
@Oldes
Copy link
Author

Oldes commented Jan 27, 2022

The output of the script (for the 2nd revision) should be:

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment