[tor-commits] [stem/master] Include sixteen auth-client lines by default

atagar at torproject.org atagar at torproject.org
Fri Nov 22 22:07:04 UTC 2019


commit f5c8c96cdd2cdc967d44ff017b68ea58ce77ca36
Author: Damian Johnson <atagar at 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



More information about the tor-commits mailing list