[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Sha256 extrainfo descriptor digests
commit 70d6e35047b3dc15fcd8438a9eb824e0105ed364
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Mon Nov 12 10:38:55 2018 -0800
Sha256 extrainfo descriptor digests
When referencing digests tor now includes both sha1 and sha256 digests. As
such, beginning to expand our digest() methods to do the same...
https://trac.torproject.org/projects/tor/ticket/28398
I'm starting with extrainfo descriptors because their hashes are referenced by
our server descriptors, providing easy test data to see if we're doing this
right or not...
% curl http://128.31.0.39:9131/tor/server/fp/3BB34C63072D9D10E836EE42968713F7B9325F66 > /tmp/my_server_desc
% curl http://128.31.0.39:9131/tor/server/extra/3BB34C63072D9D10E836EE42968713F7B9325F66 > /tmp/my_extrainfo_desc
% grep extra /tmp/my_server_desc
extra-info-digest 5BEBC13FDA976050D3A0632EE6508FD1BF1D1750 FNzZZtYPlMjBeb78Wv0zS5DUIPGB3TrpJ3k79MZURMU
% python
>>> import stem.descriptor
>>> desc = next(stem.descriptor.parse_file('/tmp/my_extrainfo_desc', 'extra-info 1.0'))
# Good! The below shows that our sha1 digest matches what our server
# descriptor says it should be.
>>> desc.digest(stem.descriptor.DigestHashType.SHA1)
'5BEBC13FDA976050D3A0632EE6508FD1BF1D1750'
# Bad! This should *not* mismatch. >:(
>>> desc.digest(stem.descriptor.DigestHashType.SHA256)
'ciuNPeDfpiBQfowP7N1g7jPsuHR9fwceTTFyknNdyvY'
Unfortunately while I'm clearly doing something wrong, I'm puzzled about why we
mismatch. Our dir-spec's extra-info-digest description is pretty clear...
"sha256-digest" is a base64-encoded SHA256 digest of the extra-info
document, computed over the same data.
We're definitely hashing the same data (otherwise the sha1 wouldn't match).
This code also certainly seems to be doing exactly what the spec says (base64
encoding the sha256 digest). So... huh.
Gonna punt this over to irl who requested this to see if he can spot what I'm
doing wrong.
---
stem/descriptor/__init__.py | 5 +++++
stem/descriptor/extrainfo_descriptor.py | 33 +++++++++++++++++++++++++++------
2 files changed, 32 insertions(+), 6 deletions(-)
diff --git a/stem/descriptor/__init__.py b/stem/descriptor/__init__.py
index 13c69f11..943106c4 100644
--- a/stem/descriptor/__init__.py
+++ b/stem/descriptor/__init__.py
@@ -118,6 +118,11 @@ skFtXhOHHqTRN4GPPrZsAIUOQGzQtGb66IQgT4tO/pj+P6QmSCCdTfhvGfgTCsC+
WPi4Fl2qryzTb3QO5r5x7T8OsG2IBUET1bLQzmtbC560SYR49IvVAgMBAAE=
"""
+DigestHashType = stem.util.enum.UppercaseEnum(
+ 'SHA1',
+ 'SHA256',
+)
+
DocumentHandler = stem.util.enum.UppercaseEnum(
'ENTRIES',
'DOCUMENT',
diff --git a/stem/descriptor/extrainfo_descriptor.py b/stem/descriptor/extrainfo_descriptor.py
index 8d8894d1..2df4bc71 100644
--- a/stem/descriptor/extrainfo_descriptor.py
+++ b/stem/descriptor/extrainfo_descriptor.py
@@ -67,6 +67,7 @@ Extra-info descriptors are available from a few sources...
===================== ===========
"""
+import base64
import functools
import hashlib
import re
@@ -79,6 +80,7 @@ import stem.util.str_tools
from stem.descriptor import (
PGP_BLOCK_END,
Descriptor,
+ DigestHashType,
create_signing_key,
_descriptor_content,
_read_until_keywords,
@@ -866,11 +868,16 @@ class ExtraInfoDescriptor(Descriptor):
else:
self._entries = entries
- def digest(self):
+ def digest(self, hash_type = DigestHashType.SHA1):
"""
Provides the upper-case hex encoded sha1 of our content. This value is part
of the server descriptor entry for this relay.
+ .. versionchanged:: 1.8.0
+ Added the hash_type argument.
+
+ :param stem.descriptor.DigestHashType hash_type: digest hashing algorithm
+
:returns: **str** with the upper-case hex digest value for this server
descriptor
"""
@@ -946,11 +953,20 @@ class RelayExtraInfoDescriptor(ExtraInfoDescriptor):
return cls(cls.content(attr, exclude, sign, signing_key), validate = validate)
@lru_cache()
- def digest(self):
+ def digest(self, hash_type = DigestHashType.SHA1):
# 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)]
- return hashlib.sha1(stem.util.str_tools._to_bytes(raw_content)).hexdigest().upper()
+ raw_content = stem.util.str_tools._to_bytes(raw_content[:raw_content.find(ending) + len(ending)])
+
+ if hash_type == DigestHashType.SHA1:
+ return hashlib.sha1(raw_content).hexdigest().upper()
+ elif hash_type == DigestHashType.SHA256:
+ # descriptors drop '=' hash padding from its fields (such as our server
+ # descriptor's extra-info-digest), so doing the same here so we match
+
+ return base64.b64encode(hashlib.sha256(raw_content).digest()).rstrip('=')
+ else:
+ raise NotImplementedError('Extrainfo descriptor digests are only available in sha1 and sha256, not %s' % hash_type)
class BridgeExtraInfoDescriptor(ExtraInfoDescriptor):
@@ -991,8 +1007,13 @@ class BridgeExtraInfoDescriptor(ExtraInfoDescriptor):
('router-digest', _random_fingerprint()),
))
- def digest(self):
- return self._digest
+ def digest(self, hash_type = DigestHashType.SHA1):
+ if hash_type == DigestHashType.SHA1:
+ return self._digest
+ elif hash_type == DigestHashType.SHA256:
+ return self.router_digest_sha256
+ else:
+ raise NotImplementedError('Bridge extrainfo digests are only available in sha1 and sha256, not %s' % hash_type)
def _required_fields(self):
excluded_fields = [
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits