[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Adding extra-info digest() method
commit 9654beb5acb7ad0e8e90bbdf7b9e186ccd946654
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Sun Jun 10 14:24:33 2012 -0700
Adding extra-info digest() method
Adding digest() methods for extra-info descriptors. I'm also swapping the
server descriptor counterparts to provide a hex encoded digest as per Karsten's
suggestion.
---
stem/descriptor/extrainfo_descriptor.py | 53 ++++++++++++++++++++++++-
stem/descriptor/server_descriptor.py | 12 +----
test/integ/descriptor/extrainfo_descriptor.py | 6 +-
test/integ/descriptor/server_descriptor.py | 2 +-
4 files changed, 59 insertions(+), 14 deletions(-)
diff --git a/stem/descriptor/extrainfo_descriptor.py b/stem/descriptor/extrainfo_descriptor.py
index 257b747..04f061a 100644
--- a/stem/descriptor/extrainfo_descriptor.py
+++ b/stem/descriptor/extrainfo_descriptor.py
@@ -45,10 +45,12 @@ Extra-info descriptors are available from a few sources...
| |- RelayExtraInfoDescriptor - Extra-info descriptor for a relay.
| +- BridgeExtraInfoDescriptor - Extra-info descriptor for a bridge.
|
+ |- digest - calculates the digest value for our content
+- get_unrecognized_lines - lines with unrecognized content
"""
import re
+import hashlib
import datetime
import stem.descriptor
@@ -673,6 +675,16 @@ class ExtraInfoDescriptor(stem.descriptor.Descriptor):
else:
self._unrecognized_lines.append(line)
+ def digest(self):
+ """
+ Provides the hex encoded sha1 of our content. This value is part of the
+ server descriptor entry for this relay.
+
+ :returns: str with the digest value for this server descriptor
+ """
+
+ raise NotImplementedError("Unsupported Operation: this should be implemented by the ExtraInfoDescriptor subclass")
+
def _required_fields(self):
return REQUIRED_FIELDS
@@ -695,9 +707,19 @@ class RelayExtraInfoDescriptor(ExtraInfoDescriptor):
def __init__(self, raw_contents, validate = True):
self.signature = None
+ self._digest = None
ExtraInfoDescriptor.__init__(self, raw_contents, validate)
+ def digest(self):
+ if self._digest is None:
+ # our digest is calculated from everything except our signature
+ raw_content, ending = str(self), "\nrouter-signature\n"
+ raw_content = raw_content[:raw_content.find(ending) + len(ending)]
+ self._digest = hashlib.sha1(raw_content).hexdigest().upper()
+
+ return self._digest
+
def _parse(self, entries, validate):
entries = dict(entries) # shallow copy since we're destructive
@@ -722,12 +744,41 @@ class BridgeExtraInfoDescriptor(ExtraInfoDescriptor):
Bridge extra-info descriptor (`specification <https://metrics.torproject.org/formats.html#bridgedesc>`_)
"""
+ def __init__(self, raw_contents, validate = True):
+ self._digest = None
+
+ ExtraInfoDescriptor.__init__(self, raw_contents, validate)
+
+ def digest(self):
+ return self._digest
+
+ def _parse(self, entries, validate):
+ entries = dict(entries) # shallow copy since we're destructive
+
+ # handles fields only in server descriptors
+ for keyword, values in entries.items():
+ value, _ = values[0]
+ line = "%s %s" % (keyword, value) # original line
+
+ if keyword == "router-digest":
+ if validate and not stem.util.tor_tools.is_hex_digits(value, 40):
+ raise ValueError("Router digest line had an invalid sha1 digest: %s" % line)
+
+ self._digest = value
+ del entries["router-digest"]
+
+ ExtraInfoDescriptor._parse(self, entries, validate)
+
def _required_fields(self):
excluded_fields = (
"router-signature",
)
- return filter(lambda e: not e in excluded_fields, REQUIRED_FIELDS)
+ included_fields = (
+ "router-digest",
+ )
+
+ return included_fields + filter(lambda e: not e in excluded_fields, REQUIRED_FIELDS)
def _last_keyword(self):
return None
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index af31f03..ec49a55 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -254,12 +254,8 @@ class ServerDescriptor(stem.descriptor.Descriptor):
def digest(self):
"""
- Provides the base64 encoded sha1 of our content. This value is part of the
- server descriptor entry for this relay.
-
- Note that network status entries exclude the padding, so you'll need to add
- a '=' to it so they'll match (`explanation
- <https://en.wikipedia.org/wiki/Base64#Padding>`_).
+ Provides the hex encoded sha1 of our content. This value is part of the
+ network status entry for this relay.
:returns: str with the digest value for this server descriptor
"""
@@ -613,9 +609,7 @@ class RelayDescriptor(ServerDescriptor):
# our digest is calculated from everything except our signature
raw_content, ending = str(self), "\nrouter-signature\n"
raw_content = raw_content[:raw_content.find(ending) + len(ending)]
-
- digest_sha1 = hashlib.sha1(raw_content).digest()
- self._digest = base64.b64encode(digest_sha1)
+ self._digest = hashlib.sha1(raw_content).hexdigest().upper()
return self._digest
diff --git a/test/integ/descriptor/extrainfo_descriptor.py b/test/integ/descriptor/extrainfo_descriptor.py
index 68b857b..d7244a9 100644
--- a/test/integ/descriptor/extrainfo_descriptor.py
+++ b/test/integ/descriptor/extrainfo_descriptor.py
@@ -43,6 +43,7 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw
self.assertEquals(datetime.datetime(2012, 5, 5, 17, 2, 45), desc.dir_write_history_end)
self.assertEquals(900, desc.dir_write_history_interval)
self.assertEquals(expected_signature, desc.signature)
+ self.assertEquals("00A57A9AAB5EA113898E2DD02A755E31AFC27227", desc.digest())
self.assertEquals([], desc.get_unrecognized_lines())
# The read-history, write-history, dirreq-read-history, and
@@ -109,9 +110,8 @@ k0d2aofcVbHr4fPQOSST0LXDrhFl5Fqo5um296zpJGvRUeO6S44U/EfJAGShtqWw
self.assertEquals(900, desc.dir_read_history_interval)
self.assertEquals(datetime.datetime(2012, 6, 8, 2, 10, 38), desc.dir_write_history_end)
self.assertEquals(900, desc.dir_write_history_interval)
-
- # TODO: uncomment when we handle router-digest entries
- #self.assertEquals([], desc.get_unrecognized_lines())
+ self.assertEquals("00A2AECCEAD3FEE033CFE29893387143146728EC", desc.digest())
+ self.assertEquals([], desc.get_unrecognized_lines())
read_values_start = [337920, 437248, 3995648, 48726016]
self.assertEquals(read_values_start, desc.read_history_values[:4])
diff --git a/test/integ/descriptor/server_descriptor.py b/test/integ/descriptor/server_descriptor.py
index 180e82c..449fb2f 100644
--- a/test/integ/descriptor/server_descriptor.py
+++ b/test/integ/descriptor/server_descriptor.py
@@ -83,7 +83,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
self.assertEquals(expected_signing_key, desc.signing_key)
self.assertEquals(expected_signature, desc.signature)
self.assertEquals([], desc.get_unrecognized_lines())
- self.assertEquals("LHsnvqsEtOJFnYnKbVzRzF+Vpok" + "=", desc.digest())
+ self.assertEquals("2C7B27BEAB04B4E2459D89CA6D5CD1CC5F95A689", desc.digest())
def test_old_descriptor(self):
"""
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits