[tor-commits] [stem/master] Mocking's sign_descriptor_content() incompatible with python 3.x

atagar at torproject.org atagar at torproject.org
Sun May 19 22:45:10 UTC 2013


commit ba50df27f2b69e05ce3470c4c1127974420a93bc
Author: Damian Johnson <atagar at torproject.org>
Date:   Sun May 19 14:11:39 2013 -0700

    Mocking's sign_descriptor_content() incompatible with python 3.x
    
    I didn't have a python 3.x copy of pycrypto installed, so there were some code
    paths I didn't previously encounter. Unit tests failed due to
    sign_descriptor_content() not explicitly using bytes at several points.
    
    ======================================================================
    ERROR: test_mirror_mirror_on_the_wall_4
    ----------------------------------------------------------------------
    Traceback:
      File "/home/atagar/Desktop/stem/test/data/python3/test/unit/tutorial.py", line 169, in test_mirror_mirror_on_the_wall_4
        exit_descriptor = mocking.sign_descriptor_content(exit_descriptor)
      File "/home/atagar/Desktop/stem/test/data/python3/test/mocking.py", line 984, in sign_descriptor_content
        public_key_string = public_key_string[:64] + "\n" + public_key_string[64:128] + "\n" + public_key_string[128:]
    TypeError: can't concat bytes to str
    
    ----------------------------------------------------------------------
---
 stem/control.py |    5 +++++
 test/mocking.py |   63 +++++++++++++++++++++++++++++++++----------------------
 2 files changed, 43 insertions(+), 25 deletions(-)

diff --git a/stem/control.py b/stem/control.py
index 08ce196..a4dde55 100644
--- a/stem/control.py
+++ b/stem/control.py
@@ -1166,6 +1166,11 @@ class Controller(BaseController):
       An exception is only raised if we weren't provided a default response.
     """
 
+    # TODO: It would be great to add support for v3 router status entries. This
+    # is pending...
+    #
+    # https://trac.torproject.org/7953
+
     try:
       if stem.util.tor_tools.is_valid_fingerprint(relay):
         query = "ns/id/%s" % relay
diff --git a/test/mocking.py b/test/mocking.py
index 340a625..50a0f0e 100644
--- a/test/mocking.py
+++ b/test/mocking.py
@@ -954,13 +954,14 @@ def get_network_status_document_v3(attr = None, exclude = (), authorities = None
 def sign_descriptor_content(desc_content):
   """
   Add a valid signature to the supplied descriptor string.
-  If the python-crypto library is available the function will generate a key
-  pair, and use it to sign the descriptor string. Any existing fingerprint,
-  signing-key or router-signature data will be overwritten.
-  If crypto is unavailable the code will return the unaltered descriptor
-  string.
-  :param string desc_content: the descriptor string to sign
-  :returns: a descriptor string, signed if crypto available, unaltered otherwise
+
+  If pycrypto is available the function will generate a key pair, and use it to
+  sign the descriptor string. Any existing fingerprint, signing-key or
+  router-signature data will be overwritten. If the library's unavailable the
+  code will return the unaltered descriptor.
+
+  :param str desc_content: the descriptor string to sign
+  :returns: a descriptor string, signed if crypto available and unaltered otherwise
   """
 
   if not stem.prereq.is_crypto_available():
@@ -981,13 +982,17 @@ def sign_descriptor_content(desc_content):
     public_key_string = base64.b64encode(seq_as_string)
 
     # split public key into lines 64 characters long
-    public_key_string = public_key_string[:64] + "\n" + public_key_string[64:128] + "\n" + public_key_string[128:]
+    public_key_string = b'\n'.join([
+      public_key_string[:64],
+      public_key_string[64:128],
+      public_key_string[128:],
+    ])
 
     # generate the new signing key string
 
-    signing_key_token = "\nsigning-key\n"  # note the trailing '\n' is important here so as not to match the string elsewhere
-    signing_key_token_start = "-----BEGIN RSA PUBLIC KEY-----\n"
-    signing_key_token_end = "\n-----END RSA PUBLIC KEY-----\n"
+    signing_key_token = b"\nsigning-key\n"  # note the trailing '\n' is important here so as not to match the string elsewhere
+    signing_key_token_start = b"-----BEGIN RSA PUBLIC KEY-----\n"
+    signing_key_token_end = b"\n-----END RSA PUBLIC KEY-----\n"
     new_sk = signing_key_token + signing_key_token_start + public_key_string + signing_key_token_end
 
     # update the descriptor string with the new signing key
@@ -998,25 +1003,25 @@ def sign_descriptor_content(desc_content):
 
     # generate the new fingerprint string
 
-    key_hash = hashlib.sha1(seq_as_string).hexdigest().upper()
-    grouped_fingerprint = ""
+    key_hash = stem.util.str_tools._to_bytes(hashlib.sha1(seq_as_string).hexdigest().upper())
+    grouped_fingerprint = b""
 
     for x in range(0, len(key_hash), 4):
-      grouped_fingerprint += " " + key_hash[x:x + 4]
-      fingerprint_token = "\nfingerprint"
+      grouped_fingerprint += b" " + key_hash[x:x + 4]
+      fingerprint_token = b"\nfingerprint"
       new_fp = fingerprint_token + grouped_fingerprint
 
     # update the descriptor string with the new fingerprint
 
     ft_start = desc_content.find(fingerprint_token)
     if ft_start < 0:
-      fingerprint_token = "\nopt fingerprint"
+      fingerprint_token = b"\nopt fingerprint"
       ft_start = desc_content.find(fingerprint_token)
 
     # if the descriptor does not already contain a fingerprint do not add one
 
     if ft_start >= 0:
-      ft_end = desc_content.find("\n", ft_start + 1)
+      ft_end = desc_content.find(b"\n", ft_start + 1)
       desc_content = desc_content[:ft_start] + new_fp + desc_content[ft_end:]
 
     # create a temporary object to use to calculate the digest
@@ -1029,31 +1034,39 @@ def sign_descriptor_content(desc_content):
 
     # remove the hex encoding
 
-    new_digest = new_digest_hex.decode('hex')
+    if stem.prereq.is_python_3():
+      new_digest = bytes.fromhex(new_digest_hex)
+    else:
+      new_digest = new_digest_hex.decode('hex_codec')
 
     # Generate the digest buffer.
     #  block is 128 bytes in size
     #  2 bytes for the type info
     #  1 byte for the separator
 
-    padding = ""
+    padding = b""
 
     for x in range(125 - len(new_digest)):
-      padding += '\xFF'
-      digestBuffer = '\x00\x01' + padding + '\x00' + new_digest
+      padding += b'\xFF'
+      digestBuffer = b'\x00\x01' + padding + b'\x00' + new_digest
 
     # generate a new signature by signing the digest buffer with the private key
 
     (signature, ) = private_key.sign(digestBuffer, None)
     signature_as_bytes = long_to_bytes(signature, 128)
     signature_base64 = base64.b64encode(signature_as_bytes)
-    signature_base64 = signature_base64[:64] + "\n" + signature_base64[64:128] + "\n" + signature_base64[128:]
+
+    signature_base64 = b'b'.join([
+      signature_base64[:64],
+      signature_base64[64:128],
+      signature_base64[128:],
+    ])
 
     # update the descriptor string with the new signature
 
-    router_signature_token = "\nrouter-signature\n"
-    router_signature_start = "-----BEGIN SIGNATURE-----\n"
-    router_signature_end = "\n-----END SIGNATURE-----\n"
+    router_signature_token = b"\nrouter-signature\n"
+    router_signature_start = b"-----BEGIN SIGNATURE-----\n"
+    router_signature_end = b"\n-----END SIGNATURE-----\n"
     rst_start = desc_content.find(router_signature_token)
     desc_content = desc_content[:rst_start] + router_signature_token + router_signature_start + signature_base64 + router_signature_end
 





More information about the tor-commits mailing list