Last active
August 29, 2015 14:16
-
-
Save DonnchaC/8c7b705402420b77f769 to your computer and use it in GitHub Desktop.
Snippets of code for calculating Tor hidden service descriptor values. Based on the descriptors in https://trac.torproject.org/projects/tor/ticket/15004#comment:4
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
import unittest | |
import hashlib | |
import struct | |
import binascii | |
from base64 import b32decode, b64decode | |
import Crypto.Util | |
from Crypto.PublicKey import RSA | |
from Crypto.Cipher import AES | |
from Crypto.Util import Counter | |
from Crypto.Util.number import bytes_to_long | |
def byte_to_int(byte): | |
return int(binascii.hexlify(byte), 16) | |
# Key Calculations | |
def get_asn1_sequence(rsa_key): | |
seq = Crypto.Util.asn1.DerSequence() | |
seq.append(rsa_key.n) | |
seq.append(rsa_key.e) | |
asn1_seq = seq.encode() | |
return asn1_seq | |
def calc_key_digest(rsa_key): | |
"""Calculate the SHA1 digest of an RSA key""" | |
return hashlib.sha1(get_asn1_sequence(rsa_key)).digest() | |
def calc_permanent_id(rsa_key): | |
return calc_key_digest(rsa_key)[:10] | |
# Descriptor Calculations | |
def get_time_period(time, permanent_id): | |
""" | |
time-period = (current-time + permanent-id-byte * 86400 / 256) / 86400 | |
""" | |
permanent_id_byte = int(struct.unpack('B', permanent_id[0])[0]) | |
return (time + permanent_id_byte * 86400 / 256) / 86400 | |
def calc_secret_id_part(time_period, replica, descriptor_cookie=None): | |
""" | |
secret-id-part = H(time-period | descriptor-cookie | replica) | |
""" | |
secret_id_part = hashlib.sha1() | |
secret_id_part.update(struct.pack('>I', time_period)[:4]) | |
if descriptor_cookie: | |
secret_id_part.update(descriptor_cookie) | |
secret_id_part.update('{0:02X}'.format(replica).decode('hex')) | |
return secret_id_part.digest() | |
def calc_descriptor_id(permanent_id, replica, time, descriptor_cookie=None): | |
time_period = get_time_period(time, permanent_id) | |
secret_id_part = calc_secret_id_part(time_period, replica, | |
descriptor_cookie) | |
descriptor_id = hashlib.sha1(permanent_id + secret_id_part).digest() | |
return descriptor_id | |
def parse_encrypted_introduction_points(introduction_point_blob, | |
descriptor_cookie): | |
BASIC_AUTH = 1 | |
STEALTH_AUTH = 2 | |
authorization_type = byte_to_int(introduction_point_blob[0]) | |
if authorization_type is BASIC_AUTH: | |
client_blocks = byte_to_int(introduction_point_blob[1]) | |
# Parse the client ID's / encrypted session keys | |
client_entries_length = client_blocks * 16 * 20 | |
client_entries = introduction_point_blob[2:2 + client_entries_length] | |
client_keys = [(client_entries[i:i+4], client_entries[i+4:i+20]) | |
for i in range(0, client_entries_length, 4 + 16)] | |
# Parse the IV and encrypted introduction points after the client keys | |
iv = introduction_point_blob[2 + client_entries_length: | |
2 + client_entries_length + 16] | |
encrypted = introduction_point_blob[2 + client_entries_length + 16:] | |
# Calculate our client ID | |
client_id = hashlib.sha1(descriptor_cookie + iv).digest()[:4] | |
for entry_id, encrypted_session_key in client_keys: | |
# Find the session key encrypted for this client | |
if entry_id == client_id: | |
# Try decrypt the session key | |
cipher = AES.new(descriptor_cookie, AES.MODE_CTR, | |
counter=Counter.new(128, initial_value=0)) | |
session_key = cipher.decrypt(encrypted_session_key) | |
# Attempt to decrypt the intro points with the session key | |
cipher = AES.new( | |
session_key, AES.MODE_CTR, | |
counter=Counter.new(128, initial_value=bytes_to_long(iv)) | |
) | |
decrypted = cipher.decrypt(encrypted) | |
# Check if the decryption looks correct | |
if decrypted.startswith("introduction-point "): | |
return decrypted | |
# If we get here, something went wrong :( | |
raise RuntimeError("The introduction points were not decrypted " | |
"successfully") | |
elif authorization_type is STEALTH_AUTH: | |
iv = introduction_point_blob[1:1 + 16] | |
encrypted = introduction_point_blob[1 + 16:] | |
cipher = AES.new( | |
descriptor_cookie, AES.MODE_CTR, | |
counter=Counter.new(128, initial_value=bytes_to_long(iv)) | |
) | |
decrypted = cipher.decrypt(encrypted) | |
if decrypted.startswith("introduction-point "): | |
return decrypted | |
else: | |
raise RuntimeError("The introduction points were not decrypted " | |
"successfully") | |
class TestDescriptorCalculations(unittest.TestCase): | |
def setUp(self): | |
self.skipTest('Parent Test Case') | |
def test_calc_permanent_id(self): | |
permanent_id = calc_permanent_id(self.permanent_key) | |
self.assertEqual(b32decode(self.onion_address, 1), permanent_id) | |
def test_calc_secret_id_part(self): | |
permanent_id = calc_permanent_id(self.permanent_key) | |
time_period = get_time_period(self.timestamp, permanent_id) | |
# Generate the secret_id_parts for both replicas | |
secret_id_parts = [] | |
for replica in range(0, 2): | |
secret_id_parts.append( | |
calc_secret_id_part(time_period=time_period, replica=replica, | |
descriptor_cookie=self.descriptor_cookie) | |
) | |
self.assertTrue(b32decode(self.secret_id_part, 1) in secret_id_parts) | |
def test_calc_descriptor_id(self): | |
permanent_id = calc_permanent_id(self.permanent_key) | |
# Generate the descriptor_id's for both replicas | |
descriptor_ids = [] | |
for replica in range(0, 2): | |
descriptor_ids.append(calc_descriptor_id( | |
permanent_id, replica, self.timestamp, self.descriptor_cookie | |
)) | |
self.assertTrue(b32decode(self.descriptor_id, 1) in descriptor_ids) | |
def test_parse_encrypted_introduction_points(self): | |
# Had to avoided setting the descriptor cookie for the basic auth | |
# example so that descriptor ID calculation would be correct. | |
descriptor_cookie = self.descriptor_cookie or self.intro_point_key | |
self.assertTrue(parse_encrypted_introduction_points( | |
self.introduction_points, descriptor_cookie | |
).startswith('introduction-point ')) | |
class TestBasicAuthDescriptorCalculations(TestDescriptorCalculations, | |
unittest.TestCase): | |
def setUp(self): | |
self.permanent_key = RSA.importKey('\n'.join([ | |
"-----BEGIN RSA PRIVATE KEY-----", | |
"MIICXQIBAAKBgQDRwt22Ua5RRZUrttrtfMARueyabyIYJSRPrtHLTME58OosiSaq", | |
"sYFOlEdYJ1yZaK0GAwuXh6DPJ2wSbuy71I2J6iDc/hJ/hZaWYU/nqi5NL/NyAeK9", | |
"BXegYMqWC8oBF1H4dG8B8GHxeJpL5emDgeiOhuYxwuOiNyx9eaq3R1uNBQIDAQAB", | |
"AoGAPT9o/ZNcEt7+b4U056NFceeX7oAEtIgj0iB5oaMHyKNPvTFO2Qh7eTZSnqrf", | |
"nuuxmc/J0rUHf3VDWR6KgU3PBa6oUkLZyshgXEysjtW4UYXAy4iHOtZ358yeQSLn", | |
"Ciz0DLqFVdwtOReYCKOIYlk+mmOdNQ67IyBDAe4Tcr0giAECQQDxIzVE09Jc7iyj", | |
"kAaj/RxWQDGlGZRvl82eZQVU4aMCO2QSHjkRGpgRsSdfIEQTb+uy4U/h0Yz9MYVV", | |
"sHYBzazpAkEA3rCWBbZcOFknNlp7G4BKj9Ky94ExmzBT+64oPoEFoKukB1Fr9KRj", | |
"nJ8UUXmLLqwsN3MAHTcWkoOAeU9vSLidvQJBAJx7TZkxoIS/5uXpk/WdTmNGWzEZ", | |
"rXLRXxTX16LinebX5bPAOyY3TNHGVZdsl+DJM3osrqsLUmQIW89kqN+4uekCQQCv", | |
"nWzCFn0FhvFQgOxi1Lp4T34Jh93595PTgBWGrTMl8RYLG1/abyWLJzzbv9FOPkMk", | |
"e1GUuJPZeVEA2e7113m1AkAQPWytigj7bp+jIoEgKBbPjT7BZP1X1ZfoaQEkR70c", | |
"RBOqte6jM17NeQQAlisIC9TWjKVFbYHkkc2n2priAb3g", | |
"-----END RSA PRIVATE KEY-----" | |
])) | |
self.introduction_points = b64decode(''.join([ | |
"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" | |
])) | |
self.onion_address = 'xpe5atmz5d26k26e' | |
# Intro point key is the descriptor_cookie, | |
self.intro_point_key = b64decode('dCmx3qIvArbil8A0KM4KgQ==') | |
self.descriptor_cookie = None # Hack to not include cookie for desc ID | |
self.timestamp = 1424808000 # 2015-02-24 20:00:00 | |
self.descriptor_id = 'yfmvdrkdbyquyqk5vygyeylgj2qmrvrd' | |
self.secret_id_part = 'fluw7z3s5cghuuirq3imh5jjj5ljips6' | |
class TestStealthAuthDescriptorCalculations(TestDescriptorCalculations, | |
unittest.TestCase): | |
def setUp(self): | |
# Use the client key for stealth authentication | |
self.permanent_key = RSA.importKey('\n'.join([ | |
"-----BEGIN RSA PRIVATE KEY-----", | |
"MIICXAIBAAKBgQC9X+xnRDmx/sTIX+BrGkwrX1R+2aWp3oAuuY59Pys/cJZKRfkk", | |
"HSL07h2tomQd+Bg09j708vfHIUsc/hNyr9oeOaUFm68CzdxY+KmvpJXJSF1nCGux", | |
"k+D3LWGcwLxyIfbfRAHuno2LvCPoeMi+kDQANm2DotXeuvqgjQgBQYAKqQIDAQAB", | |
"AoGAC7Mudt7XNbEI1VxfEB7qz88u+DtYKduOTdS3AfPyJxQ8pNAX6WxHaZyAhua+", | |
"ir92N2dzUkzklA/xhRQJfY9xyUruu8aOrBW6UzZE76s2PQyClgU2jWUi3PVDjoag", | |
"7CrKkBM3/IPq34b6IEIffp68iOFIhStjQHBUpnMlHuBzrAUCQQDyl2JtQAoOK17x", | |
"ZePx8u/jSxnbT2b6vQQ9334KKrEagFmdfHx8uBktkjWgdM2nrX4/TUqgAke3Iz/v", | |
"CIN82mQTAkEAx9eI7KaRyts3EQ4vNJIDxZOglVVIR09xMFhXWfqYRE2PdthqG82E", | |
"JKAJMf9MYYd69XTqjdUud2lxMfkKeM4V0wJAUEAkH1//85AFaHX8Yh2rndVKSHKL", | |
"7oZ40L8OQu68h7fN7Xsw81Ezgw/LDbmWDtIl4WsANM6MStkuXTTDypm0YQJBAJx9", | |
"c4OdjF1F/IEmkmCgVsPJLt7Bwa/VzdUF2KFlUwdplQaDwdOzw97KU2kLekyFQwwj", | |
"WelnHtPzheiUFFc1SnECQClXuBVw/mIoac6mbuw83uhLwSip3Aid8NpDgqQKNQAP", | |
"pRDzVrFeiNNWcvTfiZyM4HvXAK2xD+XNSi8CtSu3zuQ=", | |
"-----END RSA PRIVATE KEY-----" | |
])) | |
self.introduction_points = b64decode(''.join([ | |
"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" | |
])) | |
self.onion_address = 'tosbmbgysyldansp' | |
self.descriptor_cookie = b64decode('dCmx3qIvArbil8A0KM4KgR==') | |
self.timestamp = 1424808000 # 2015-02-24 20:00:00 | |
self.descriptor_id = 'ubf3xeibzlfil6s4larq6y5peup2z3oj' | |
self.secret_id_part = 'jczvydhzetbpdiylj3d5nsnjvaigs7xm' | |
if __name__ == '__main__': | |
unittest.main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment