[tor-commits] [stem/master] Adding _to_int() helper to str_tools

atagar at torproject.org atagar at torproject.org
Thu Mar 30 04:18:03 UTC 2017


commit 15ed89f92087d50c0646b373e8c43153948550e9
Author: Damian Johnson <atagar at torproject.org>
Date:   Tue Mar 21 21:40:51 2017 +0100

    Adding _to_int() helper to str_tools
    
    Replacing our cert module's _bytes_to_long() helper with a tested counterpart
    in str_tools. Not sure if it matters but should be more efficient. Rather than
    doing a 'unicode => bytes => hex => int' conversion we directly convert to the
    integer representation.
---
 stem/descriptor/certificate.py | 18 ++++++------------
 stem/util/str_tools.py         | 16 ++++++++++++++++
 test/unit/util/str_tools.py    | 17 +++++++++++++++++
 3 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/stem/descriptor/certificate.py b/stem/descriptor/certificate.py
index 528d594..191e87e 100644
--- a/stem/descriptor/certificate.py
+++ b/stem/descriptor/certificate.py
@@ -2,8 +2,8 @@
 # See LICENSE for licensing information
 
 """
-Parsing for the Tor server descriptor Ed25519 Certificates, which is used to
-validate the Ed25519 key used to sign the relay descriptor.
+Parsing for Tor Ed25519 certificates, which is used to validate the key used to
+sign server descriptors.
 
 Certificates can optionally contain CertificateExtension objects depending on
 their type and purpose. Currently Ed25519KeyCertificate certificates will
@@ -41,16 +41,9 @@ CERTIFICATE_FLAGS_LENGTH = 4
 ED25519_ROUTER_SIGNATURE_PREFIX = b'Tor router descriptor signature v1'
 
 
-def _bytes_to_long(b):
-  if stem.prereq.is_python_3():
-    return int(binascii.hexlify(stem.util.str_tools._to_bytes(b)), 16)
-  else:
-    return long(binascii.hexlify(b), 16)
-
-
 def _parse_long_offset(offset, length):
   def _parse(raw_contents):
-    return _bytes_to_long(raw_contents[offset:(offset + length)])
+    return stem.util.str_tools._to_int(raw_contents[offset:(offset + length)])
 
   return _parse
 
@@ -82,7 +75,8 @@ def _parse_certificate(raw_contents, master_key_bytes, validate = False):
 
 
 def _parse_extensions(raw_contents):
-  n_extensions = _bytes_to_long(raw_contents[39:40])
+  n_extensions = stem.util.str_tools._to_int(raw_contents[39:40])
+
   if n_extensions == 0:
     return []
 
@@ -90,7 +84,7 @@ def _parse_extensions(raw_contents):
   extension_bytes = raw_contents[STANDARD_ATTRIBUTES_LENGTH:-SIGNATURE_LENGTH]
 
   while len(extension_bytes) > 0:
-    ext_length = _bytes_to_long(extension_bytes[0:2])
+    ext_length = stem.util.str_tools._to_int(extension_bytes[0:2])
     ext_type = extension_bytes[2:3]
     ext_flags = extension_bytes[3:CERTIFICATE_FLAGS_LENGTH]
     ext_data = extension_bytes[CERTIFICATE_FLAGS_LENGTH:(CERTIFICATE_FLAGS_LENGTH + ext_length)]
diff --git a/stem/util/str_tools.py b/stem/util/str_tools.py
index 0fbdf38..8c6463a 100644
--- a/stem/util/str_tools.py
+++ b/stem/util/str_tools.py
@@ -117,6 +117,22 @@ def _to_unicode(msg):
   return _to_unicode_impl(msg)
 
 
+def _to_int(msg):
+  """
+  Serializes a string to a number.
+
+  :param str msg: string to be serialized
+
+  :returns: **int** representation of the string
+  """
+
+  if stem.prereq.is_python_3() and isinstance(msg, bytes):
+    # iterating over bytes in python3 provides ints rather than characters
+    return sum([pow(256, (len(msg) - i - 1)) * c for (i, c) in enumerate(msg)])
+  else:
+    return sum([pow(256, (len(msg) - i - 1)) * ord(c) for (i, c) in enumerate(msg)])
+
+
 def _to_camel_case(label, divider = '_', joiner = ' '):
   """
   Converts the given string to camel case, ie:
diff --git a/test/unit/util/str_tools.py b/test/unit/util/str_tools.py
index 3d0936f..00e5c55 100644
--- a/test/unit/util/str_tools.py
+++ b/test/unit/util/str_tools.py
@@ -9,6 +9,23 @@ from stem.util import str_tools
 
 
 class TestStrTools(unittest.TestCase):
+  def test_to_int(self):
+    """
+    Checks the _to_int() function.
+    """
+
+    test_inputs = {
+      '': 0,
+      'h': 104,
+      'hi': 26729,
+      'hello': 448378203247,
+      str_tools._to_bytes('hello'): 448378203247,
+      str_tools._to_unicode('hello'): 448378203247,
+    }
+
+    for arg, expected in test_inputs.items():
+      self.assertEqual(expected, str_tools._to_int(arg))
+
   def test_to_camel_case(self):
     """
     Checks the _to_camel_case() function.





More information about the tor-commits mailing list