aboutsummaryrefslogtreecommitdiff
path: root/tor-spec.txt
diff options
context:
space:
mode:
authorEmil Engler <me@emilengler.com>2023-06-17 22:57:42 +0200
committerEmil Engler <me@emilengler.com>2023-06-21 13:04:05 +0200
commite67c9afd100a8822a5aa4e8201a56eb2cf5374af (patch)
treed6bcdef88630cf5bdaea54b930fc77675c7fe245 /tor-spec.txt
parente6326aa805d7ffb782d4136c9e5274bc64937274 (diff)
downloadtorspec-e67c9afd100a8822a5aa4e8201a56eb2cf5374af.tar.gz
torspec-e67c9afd100a8822a5aa4e8201a56eb2cf5374af.zip
tor-spec: provide pseudocode for digest check
This commit implements a pseudocode example for the digest in both: encryption and decryption cases. The pseudocode itself is a combination of Python code and the Rust slice type. Fixes #205
Diffstat (limited to 'tor-spec.txt')
-rw-r--r--tor-spec.txt43
1 files changed, 43 insertions, 0 deletions
diff --git a/tor-spec.txt b/tor-spec.txt
index b42ee26..669851f 100644
--- a/tor-spec.txt
+++ b/tor-spec.txt
@@ -49,6 +49,7 @@ Table of Contents
5.6. Handling relay_early cells
6. Application connections and stream management
6.1. Relay cells
+ 6.1.1. Calculating the 'Digest' field
6.2. Opening streams and transferring data
6.2.1. Opening a directory stream
6.3. Closing streams
@@ -1791,6 +1792,48 @@ see tor-design.pdf.
understood, the cell must be dropped and ignored. Its contents
still count with respect to the digests and flow control windows, though.
+6.1.1. Calculating the 'Digest' field
+
+ The 'Digest' field itself serves the purpose to check if a cell has been
+ fully decrypted, that is, all onion layers have been removed. Having a
+ single field, namely 'Recognized' is not sufficient, as outlined above.
+
+ When ENCRYPTING a RELAY cell, an implementation does the following:
+
+ # Encode the cell in binary (recognized and digest set to zero)
+ tmp = cmd + [0, 0] + stream_id + [0, 0, 0, 0] + length + data + padding
+
+ # Update the digest with the encoded data
+ digest_state = hash_update(digest_state, tmp)
+ digest = hash_calculate(digest_state)
+
+ # The encoded data is the same as above with the digest field not being
+ # zero anymore
+ encoded = cmd + [0, 0] + stream_id + digest[0..4] + length + data +
+ padding
+
+ # Now we can encrypt the cell by adding the onion layers ...
+
+ When DECRYPTING a RELAY cell, an implementation does the following:
+
+ decrypted = decrypt(cell)
+
+ # Replace the digest field in decrypted by zeros
+ tmp = decrypted[0..5] + [0, 0, 0, 0] + decrypted[9..]
+
+ # Update the digest field with the decrypted data and its digest field
+ # set to zero
+ digest_state = hash_update(digest_state, tmp)
+ digest = hash_calculate(digest_state)
+
+ if digest[0..4] == decrypted[5..9]
+ # The cell has been fully decrypted ...
+
+ The caveat itself is that only the binary data with the digest bytes set to
+ zero are being taken into account when calculating the running digest. The
+ final plain-text cells (with the digest field set to its actual value) are
+ not taken into the running digest.
+
6.2. Opening streams and transferring data
To open a new anonymized TCP connection, the OP chooses an open