[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [stem/master] Separate hidden service decryption from constructor
commit 14a44b1c6e1438abdf5687a1c468536d88481f81
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Sun Sep 22 14:02:06 2019 -0700
Separate hidden service decryption from constructor
Moving hidden service description from the constructor into a method for a
couple reasons...
1. Wherever possible we lazy rather than eagerly evaluate descriptor content.
We do not know upfront what fields our user will want, so best to avoid
doing unnecessarily decryption (which is particularly cpu intensive)
unless our user indicates that they want this content.
2. We cannot modify constructor signatures without plumbing arguments through
several other methods. Not necessarily a no-go, but decryption requires an
onion_address whereas construction does not so separating this into its
own method sidesteps that headache.
---
stem/descriptor/hidden_service.py | 32 ++++++++++---------------------
test/unit/descriptor/hidden_service_v3.py | 5 +++--
2 files changed, 13 insertions(+), 24 deletions(-)
diff --git a/stem/descriptor/hidden_service.py b/stem/descriptor/hidden_service.py
index fc898f93..fda5147b 100644
--- a/stem/descriptor/hidden_service.py
+++ b/stem/descriptor/hidden_service.py
@@ -530,16 +530,10 @@ class HiddenServiceDescriptorV3(BaseHiddenServiceDescriptor):
def create(cls, attr = None, exclude = (), validate = True, sign = False):
return cls(cls.content(attr, exclude, sign), validate = validate, skip_crypto_validation = not sign)
- def __init__(self, raw_contents, validate = False, onion_address = None, skip_crypto_validation = False):
- """
- The onion_address is needed so that we can decrypt the descriptor, which is
- impossible without the full onion address.
- """
+ def __init__(self, raw_contents, validate = False, skip_crypto_validation = False):
super(HiddenServiceDescriptorV3, self).__init__(raw_contents, lazy_load = not validate)
entries = _descriptor_components(raw_contents, validate)
- self.onion_address = onion_address
- # XXX Do this parsing in its own function
if validate:
for keyword in REQUIRED_V3_FIELDS:
if keyword not in entries:
@@ -556,23 +550,17 @@ class HiddenServiceDescriptorV3(BaseHiddenServiceDescriptor):
else:
self._entries = entries
- # crypto validation (check skip_crypto_validation)
- # ASN XXX need to verify descriptor signing certificate (for now we trust Tor to do it)
- # ASN XXX need to verify descriptor signature (for now we trust Tor to do it)
-
- if not skip_crypto_validation and stem.prereq.is_crypto_available():
- if self.onion_address is None:
- raise ValueError('Onion address is required to decrypt v3 hidden service descriptors')
+ # TODO: The following is only marked as private because it is a work in
+ # progress. This will probably become something like "body()" which decrypts
+ # and parses the internal descriptor content.
- # ATAGAR XXX need to do this cert extraction in the parsing handler
- assert(self.signing_cert)
- cert_lines = self.signing_cert.split('\n')
- assert(cert_lines[0] == '-----BEGIN ED25519 CERT-----' and cert_lines[-1] == '-----END ED25519 CERT-----')
+ def _decrypt(self, onion_address):
+ assert(self.signing_cert)
+ cert_lines = self.signing_cert.split('\n')
+ assert(cert_lines[0] == '-----BEGIN ED25519 CERT-----' and cert_lines[-1] == '-----END ED25519 CERT-----')
- desc_signing_cert = stem.descriptor.certificate.Ed25519Certificate.parse(''.join(cert_lines[1:-1]))
- self.plaintext = self.decrypt_descriptor(desc_signing_cert)
+ desc_signing_cert = stem.descriptor.certificate.Ed25519Certificate.parse(''.join(cert_lines[1:-1]))
- def decrypt_descriptor(self, desc_signing_cert):
# Get crypto material.
# ASN XXX Extract to its own function and assign them to class variables
from cryptography.hazmat.primitives import serialization
@@ -585,7 +573,7 @@ class HiddenServiceDescriptorV3(BaseHiddenServiceDescriptor):
if not blinded_key_bytes:
raise ValueError('No signing key extension present')
- identity_public_key = stem.descriptor.hsv3_crypto.decode_address(self.onion_address)
+ identity_public_key = stem.descriptor.hsv3_crypto.decode_address(onion_address)
identity_public_key_bytes = identity_public_key.public_bytes(encoding=serialization.Encoding.Raw,
format=serialization.PublicFormat.Raw)
assert(len(identity_public_key_bytes) == 32)
diff --git a/test/unit/descriptor/hidden_service_v3.py b/test/unit/descriptor/hidden_service_v3.py
index 98de246e..ac2f8ea7 100644
--- a/test/unit/descriptor/hidden_service_v3.py
+++ b/test/unit/descriptor/hidden_service_v3.py
@@ -44,13 +44,14 @@ class TestHiddenServiceDescriptorV3(unittest.TestCase):
return
with open(get_resource('hidden_service_v3_test'), 'rb') as descriptor_file:
- desc = next(stem.descriptor.parse_file(descriptor_file, 'hidden-service-descriptor-3 1.0', validate = True,
- onion_address = 'sltib6sxkuxh2scmtuvd5w2g7pahnzkovefxpo4e4ptnkzl5kkq5h2ad.onion'))
+ desc = next(stem.descriptor.parse_file(descriptor_file, 'hidden-service-descriptor-3 1.0', validate = True))
self.assertEqual(3, desc.version)
self.assertEqual(180, desc.lifetime)
self.assertEqual(42, desc.revision_counter)
+ desc._decrypt('sltib6sxkuxh2scmtuvd5w2g7pahnzkovefxpo4e4ptnkzl5kkq5h2ad.onion')
+
def test_for_riseup(self):
"""
Parse riseup's descriptor...
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits