[tor-commits] [stem/master] Support hash types and encodings for server descriptor digests
atagar at torproject.org
atagar at torproject.org
Thu Nov 15 20:29:50 UTC 2018
commit de42798f432d05fc1e7d626ab8ce311b1368f5f0
Author: Damian Johnson <atagar at torproject.org>
Date: Thu Nov 15 11:56:20 2018 -0800
Support hash types and encodings for server descriptor digests
Replicating what I just did for extrainfo descriptors with server descriptors.
---
stem/descriptor/extrainfo_descriptor.py | 5 ++--
stem/descriptor/server_descriptor.py | 38 ++++++++++++++++++++++++-------
test/unit/descriptor/server_descriptor.py | 1 +
3 files changed, 33 insertions(+), 11 deletions(-)
diff --git a/stem/descriptor/extrainfo_descriptor.py b/stem/descriptor/extrainfo_descriptor.py
index 4319bb05..401b9643 100644
--- a/stem/descriptor/extrainfo_descriptor.py
+++ b/stem/descriptor/extrainfo_descriptor.py
@@ -966,9 +966,8 @@ class RelayExtraInfoDescriptor(ExtraInfoDescriptor):
if hash_type == DigestHash.SHA1:
# our digest is calculated from everything except our signature
- raw_content, ending = str(self), '\nrouter-signature\n'
- raw_content = stem.util.str_tools._to_bytes(raw_content[:raw_content.find(ending) + len(ending)])
- return stem.descriptor._encode_digest(hashlib.sha1(raw_content), encoding)
+ content = self._content_range(end = '\nrouter-signature\n')
+ return stem.descriptor._encode_digest(hashlib.sha1(content), encoding)
elif hash_type == DigestHash.SHA256:
# Due to a tor bug sha256 digests are calculated from the
# whole descriptor rather than ommiting the signature...
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index 0d12f875..748a2a9d 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -68,6 +68,8 @@ from stem.descriptor.router_status_entry import RouterStatusEntryV3
from stem.descriptor import (
PGP_BLOCK_END,
Descriptor,
+ DigestHash,
+ DigestEncoding,
create_signing_key,
_descriptor_content,
_descriptor_components,
@@ -654,12 +656,22 @@ class ServerDescriptor(Descriptor):
else:
self._entries = entries
- def digest(self):
+ def digest(self, hash_type = DigestHash.SHA1, encoding = DigestEncoding.HEX):
"""
- Provides the hex encoded sha1 of our content. This value is part of the
- network status entry for this relay.
+ Digest of this descriptor's content. These are referenced by...
- :returns: **unicode** with the upper-case hex digest value for this server descriptor
+ * **Consensus**
+
+ * Referer: :class:`~stem.descriptor.router_status_entry.RouterStatusEntryV3` **digest** attribute
+ * Format: **SHA1/BASE64**
+
+ .. versionchanged:: 1.8.0
+ Added the hash_type and encoding arguments.
+
+ :param stem.descriptor.DigestHash hash_type: digest hashing algorithm
+ :param stem.descriptor.DigestEncoding encoding: digest encoding
+
+ :returns: **hashlib.HASH** or **str** based on our encoding argument
"""
raise NotImplementedError('Unsupported Operation: this should be implemented by the ServerDescriptor subclass')
@@ -890,7 +902,7 @@ class RelayDescriptor(ServerDescriptor):
return cls(cls.content(attr, exclude, sign, signing_key), validate = validate, skip_crypto_validation = not sign)
@lru_cache()
- def digest(self):
+ def digest(self, hash_type = DigestHash.SHA1, encoding = DigestEncoding.HEX):
"""
Provides the digest of our descriptor's content.
@@ -899,7 +911,14 @@ class RelayDescriptor(ServerDescriptor):
:raises: ValueError if the digest cannot be calculated
"""
- return self._digest_for_content(b'router ', b'\nrouter-signature\n')
+ content = self._content_range(start = 'router', end = '\nrouter-signature\n')
+
+ if hash_type == DigestHash.SHA1:
+ return stem.descriptor._encode_digest(hashlib.sha1(content), encoding)
+ elif hash_type == DigestHash.SHA256:
+ return stem.descriptor._encode_digest(hashlib.sha256(content), encoding)
+ else:
+ raise NotImplementedError('Server descriptor digests are only available in sha1 and sha256, not %s' % hash_type)
def make_router_status_entry(self):
"""
@@ -1026,8 +1045,11 @@ class BridgeDescriptor(ServerDescriptor):
('reject', '*:*'),
))
- def digest(self):
- return self._digest
+ def digest(self, hash_type = DigestHash.SHA1, encoding = DigestEncoding.HEX):
+ if hash_type == DigestHash.SHA1 and encoding == DigestEncoding.HEX:
+ return self._digest
+ else:
+ raise NotImplementedError('Bridge server descriptor digests are only available as sha1/hex, not %s/%s' % (hash_type, encoding))
def is_scrubbed(self):
"""
diff --git a/test/unit/descriptor/server_descriptor.py b/test/unit/descriptor/server_descriptor.py
index ec1af553..796286c5 100644
--- a/test/unit/descriptor/server_descriptor.py
+++ b/test/unit/descriptor/server_descriptor.py
@@ -154,6 +154,7 @@ Qlx9HNCqCY877ztFRC624ja2ql6A2hBcuoYMbkHjcQ4=
self.assertEqual(expected_signature, desc.signature)
self.assertEqual([], desc.get_unrecognized_lines())
self.assertEqual('2C7B27BEAB04B4E2459D89CA6D5CD1CC5F95A689', desc.digest())
+ self.assertEqual('LHsnvqsEtOJFnYnKbVzRzF+Vpok', desc.digest(encoding = stem.descriptor.DigestEncoding.BASE64))
self.assertEqual('@type server-descriptor 1.0', str(desc.type_annotation()))
self.assertEqual(['2'], desc.hidden_service_dir) # obsolete field
More information about the tor-commits
mailing list