[tor-commits] [stem/master] Generate broken server descriptor signaures

atagar at torproject.org atagar at torproject.org
Tue Jun 20 16:17:12 UTC 2017


commit edfe4d07154f5902ca8f52903923f02d2e943e76
Author: Damian Johnson <atagar at torproject.org>
Date:   Sun Jun 18 19:34:40 2017 -0700

    Generate broken server descriptor signaures
    
    This does *not* work yet but feels like we're making progress. This generates
    validly looking descriptors, now just gotta get all the crypto right...
---
 stem/descriptor/server_descriptor.py | 37 ++++++++++++++++++++++++++++++++++--
 1 file changed, 35 insertions(+), 2 deletions(-)

diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index 20948dd..8bafda5 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -239,6 +239,23 @@ def _generate_signing_key():
   return SigningKey(public_key, private_key, pem)
 
 
+def _generate_signature(content, signing_key):
+  """
+  Creates the 'router-signature' for the given descriptor content.
+  """
+
+  from cryptography.hazmat.primitives import hashes
+  from cryptography.hazmat.primitives.asymmetric import padding
+
+  # generate the digest with required PKCS1 padding so it's 128 bytes
+
+  digest = hashlib.sha1(content).hexdigest().lower().decode('hex_codec')
+  digest = b'\x00\x01' + (b'\xFF' * (125 - len(digest))) + b'\x00' + digest
+
+  padding = padding.PSS(mgf = padding.MGF1(hashes.SHA256()), salt_length = padding.PSS.MAX_LENGTH)
+  return base64.b64encode(signing_key.private.sign(digest, padding, hashes.SHA256()))
+
+
 def _parse_router_line(descriptor, entries):
   # "router" nickname address ORPort SocksPort DirPort
 
@@ -846,14 +863,30 @@ class RelayDescriptor(ServerDescriptor):
 
   @classmethod
   def content(cls, attr = None, exclude = (), sign = False):
-    if sign and (not attr or 'signing-key' not in attr):
+    if sign:
+      if not stem.prereq.is_crypto_available():
+        raise ImportError('Signing requires the cryptography module')
+      elif attr and 'signing-key' in attr:
+        raise ValueError('Cannot sign the descriptor if a signing-key has been provided')
+      elif attr and 'router-signature' in attr:
+        raise ValueError('Cannot sign the descriptor if a router-signature has been provided')
+
       if attr is None:
         attr = {}
 
+      # create descriptor content without the router-signature line, then
+      # appending the signature
+
       signing_key = _generate_signing_key()
       attr['signing-key'] = signing_key.descriptor_signing_key
+      content = _descriptor_content(attr, exclude, sign, RELAY_SERVER_HEADER)
+
+      signature = _generate_signature(content, signing_key)
+      content = '\n'.join([content, 'router-signature', '-----BEGIN SIGNATURE-----'] + stem.util.str_tools._split_by_length(signature, 64) + ['-----END SIGNATURE-----'])
 
-    return _descriptor_content(attr, exclude, sign, RELAY_SERVER_HEADER, RELAY_SERVER_FOOTER)
+      return content
+    else:
+      return _descriptor_content(attr, exclude, sign, RELAY_SERVER_HEADER, RELAY_SERVER_FOOTER)
 
   @classmethod
   def create(cls, attr = None, exclude = (), validate = True, sign = False):





More information about the tor-commits mailing list