commit f5c8c96cdd2cdc967d44ff017b68ea58ce77ca36 Author: Damian Johnson atagar@torproject.org Date: Fri Nov 22 14:03:14 2019 -0800
Include sixteen auth-client lines by default
auth-client are a required field...
https://trac.torproject.org/projects/tor/ticket/32563 https://trac.torproject.org/projects/tor/ticket/31823#comment:16
Tor creates sixteen by default, so doing the same unless our caller specifies otherwise.
% cat demo.py from stem.descriptor.hidden_service import OuterLayer
print(OuterLayer.create())
% python demo.py desc-auth-type x25519 desc-auth-ephemeral-key fhUEgYTR3j4/8MC8aH75WTIKWFOzvKiXURvPHdIXTH4= auth-client 1J4LPB+umNA iOGHkI+vpsWJaugbv6akgg EtisFxHd3buXMcl30uxJ8A auth-client wbmXMy71u+Q aiFlaQQV3hBPrmOaQ8kXDg HP+ZFqEt0z47F5AVBnyzxA auth-client ahHWCcU8INM kQrwT8jZOXAdxiyeVZ/EWw tIBpoOqhvoGhFCOceSLZXA auth-client UrnUpDYoCTs 6VC/C7xcIWd4Dtmrj1nKig 1k2hfoPhGPwX4BORgHeDPw auth-client 5I03RmlXJps rgdrWYmq02EmMF+v7PMoLw lkxQtmEz3+CVniXM0E16vQ auth-client ub0ap7cdghQ gGjmEJTYcw6RGwri2DlPaQ Wz+vnYEc2PmeFxM85lNCcg auth-client TLgL1NsDjIU bKuIgs/blO3mL80mC13JDw 8sjbuwv3o9sQTt0yQbhIxw auth-client aytYGQGGAkE lqg3uBRYIX9DHjWl8aLmxQ Nsb6dvhnykFJtSyeGekUhw auth-client htPYuHAyOsA Wim8CZKo3o2toq+dqeGgMg m6vIoCpQWT0JRR+JgcHIqw auth-client oJJr9IpqKpc gwd5SFc0CWtRMAaZaqWQrQ iA8qoyKVXWs2N6DA9WzqiQ auth-client EEIi97LqhGA K+Vn6P2dfRgFZXHhgBvX9A 9bXjd6UBUXuBY3/aeNCR5w auth-client 1JCG9WKhPKY CgMjZquv+KPLzpqn72uMKQ kC6e5GM/1+2TIvq8kb47Lw auth-client 6MuN+1vob4w Wi1ktyiaiOaG6PaLbneydQ OEigSskYEZb8hGqWZMDKlg auth-client uOoXx8epem4 /VjgpZzC71Gj6WAXuVXzVw Q4dOW6GYc/JoQrKNLUQmbQ auth-client aC9d6RbIr1M FCY56VPOLEktEsQiCDrORQ 0fAhfjriUxnFvbjiTfGDrw auth-client 60vj3crxSwg XSytZMniMFUCDYbhyrdhDg 3P5Q5QaI70AvX/d8Wh7Etw encrypted -----BEGIN MESSAGE----- EqEXDglNZxN+TmE6I7U7fd9DM0ue9ys770n6AnH4ga+fLSJ8AOb0lX4XANG9TuFh 6hyOfGa0joPezoQSeAFf+yk= -----END MESSAGE----- --- stem/descriptor/hidden_service.py | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/stem/descriptor/hidden_service.py b/stem/descriptor/hidden_service.py index e75c7a6e..983fb94b 100644 --- a/stem/descriptor/hidden_service.py +++ b/stem/descriptor/hidden_service.py @@ -1183,9 +1183,13 @@ class OuterLayer(Descriptor): return _encrypt_layer(content, b'hsdir-superencrypted-data', revision_counter, subcredential, blinded_key)
@classmethod - def content(cls, attr = None, exclude = (), validate = True, sign = False, inner_layer = None, revision_counter = None, subcredential = None, blinded_key = None): + def content(cls, attr = None, exclude = (), validate = True, sign = False, inner_layer = None, revision_counter = None, authorized_clients = None, subcredential = None, blinded_key = None): if not stem.prereq.is_crypto_available(ed25519 = True): raise ImportError('Hidden service layer creation requires cryptography version 2.6') + elif not stem.prereq._is_sha3_available(): + raise ImportError('Hidden service layer creation requires python 3.6+ or the pysha3 module (https://pypi.org/project/pysha3/)') + elif authorized_clients and 'auth-client' in attr: + raise ValueError('Authorized clients cannot be specified through both attr and authorized_clients')
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey @@ -1195,16 +1199,31 @@ class OuterLayer(Descriptor): blinded_key = blinded_key if blinded_key else stem.util._pubkey_bytes(Ed25519PrivateKey.generate()) subcredential = subcredential if subcredential else HiddenServiceDescriptorV3._subcredential(Ed25519PrivateKey.generate(), blinded_key)
- return _descriptor_content(attr, exclude, ( + if not authorized_clients: + authorized_clients = [] + + if attr and 'auth-client' in attr: + pass # caller is providing raw auth-client lines through the attr + else: + for i in range(16): + client_id = base64.b64encode(os.urandom(8)).rstrip(b'=') + iv = base64.b64encode(os.urandom(16)).rstrip(b'=') + cookie = base64.b64encode(os.urandom(16)).rstrip(b'=') + + authorized_clients.append(AuthorizedClient(client_id, iv, cookie)) + + return _descriptor_content(attr, exclude, [ ('desc-auth-type', 'x25519'), ('desc-auth-ephemeral-key', base64.b64encode(stem.util._pubkey_bytes(X25519PrivateKey.generate()))), - ), ( + ] + [ + ('auth-client', '%s %s %s' % (c.id, c.iv, c.cookie)) for c in authorized_clients + ], ( ('encrypted', b'\n' + inner_layer._encrypt(revision_counter, subcredential, blinded_key)), ))
@classmethod - def create(cls, attr = None, exclude = (), validate = True, sign = False, inner_layer = None, revision_counter = None, subcredential = None, blinded_key = None): - return cls(cls.content(attr, exclude, validate, sign, inner_layer, revision_counter, subcredential, blinded_key), validate = validate) + def create(cls, attr = None, exclude = (), validate = True, sign = False, inner_layer = None, revision_counter = None, authorized_clients = None, subcredential = None, blinded_key = None): + return cls(cls.content(attr, exclude, validate, sign, inner_layer, revision_counter, authorized_clients, subcredential, blinded_key), validate = validate)
def __init__(self, content, validate = False): content = stem.util.str_tools._to_bytes(content).rstrip(b'\x00') # strip null byte padding