I’m not sure which category this should best belong to, but here goes:
I’m reading through the specification and looking through the code (a slightly modified torpy), and I can’t figure out what the handshake_response
should be.
According to CREATE and CREATED cells - Tor Specifications and
Setting circuit keys - Tor Specifications, both the OP and the first hop generate random key material:
def handshake(self):
return secrets.token_bytes(TOR_DIGEST_LEN)
and then the OP sends it X to the first hop, and the first hop responds with a handshake_response
such that with it we can
def complete_handshake(self, handshake_response):
# tor ref: fast_client_handshake
peer_value = handshake_response[:TOR_DIGEST_LEN]
key_hash = handshake_response[TOR_DIGEST_LEN:]
shared_secret = self.handshake + peer_value
computed_auth, key_material = kdf_tor(shared_secret)
if computed_auth != key_hash:
raise KeyAgreementError('Auth input does not match.')
return key_material[:KeyAgreement.KEY_MATERIAL_LENGTH]
, where
def tor_digest(msg):
return sha1(msg)
def kdf_tor(shared_secret):
# tor ref: crypto_expand_key_material_TAP
t = shared_secret + bytes([0])
computed_auth = tor_digest(t)
key_material = b''
for i in trange(1, 5):
t = shared_secret + bytes([i])
tsh = tor_digest(t)
key_material += tsh
return computed_auth, key_material
So, how do we calculate the handshake_response
? Am I being slow and missing something?
I tried looking into the source (Tor: core/crypto/onion_fast.c Source File), but I’m not that good with C, so I didn’t really get it from there either.