commit f1312056f0a00132b19d247a4d0b53ff689b066d Author: Damian Johnson atagar@torproject.org Date: Fri Oct 11 14:56:26 2019 -0700
Check for openssl ed25519 support
Unit tests fail with several errors, the most common of which for me is a lack of ed25519 support in openssl...
====================================================================== ERROR: test_inner_layer ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/atagar/Desktop/stem/test/unit/descriptor/hidden_service_v3.py", line 119, in test_inner_layer self.assertEqual(4, len(desc.introduction_points)) File "/home/atagar/Desktop/stem/stem/descriptor/__init__.py", line 1149, in __getattr__ parsing_function(self, self._entries) File "/home/atagar/Desktop/stem/stem/descriptor/hidden_service.py", line 447, in _parse_v3_introduction_points enc_key = X25519PublicKey.from_public_bytes(base64.b64decode(enc_key_b64)) File "/usr/local/lib/python3.5/dist-packages/cryptography/hazmat/primitives/asymmetric/x25519.py", line 22, in from_public_bytes _Reasons.UNSUPPORTED_EXCHANGE_ALGORITHM cryptography.exceptions.UnsupportedAlgorithm: X25519 is not supported by this version of OpenSSL.
This is gonna require more work, but for the moment disabling these portions when unavailable to cut down on test failures. --- stem/descriptor/hidden_service.py | 42 +++++++++++++++++++------------ test/unit/descriptor/hidden_service_v3.py | 13 ++++++++++ 2 files changed, 39 insertions(+), 16 deletions(-)
diff --git a/stem/descriptor/hidden_service.py b/stem/descriptor/hidden_service.py index 5f97a25a..b6116358 100644 --- a/stem/descriptor/hidden_service.py +++ b/stem/descriptor/hidden_service.py @@ -409,6 +409,7 @@ def _parse_v3_inner_formats(descriptor, entries):
def _parse_v3_introduction_points(descriptor, entries): + from cryptography.hazmat.backends.openssl.backend import backend from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PublicKey
if hasattr(descriptor, '_unparsed_introduction_points'): @@ -428,9 +429,12 @@ def _parse_v3_introduction_points(descriptor, entries): entry = _descriptor_components(intro_point_str, False) link_specifiers = _parse_link_specifiers(_value('introduction-point', entry))
- onion_key_line = _value('onion-key', entry) - onion_key_b64 = onion_key_line[5:] if onion_key_line.startswith('ntor ') else None - onion_key = X25519PublicKey.from_public_bytes(base64.b64decode(onion_key_b64)) + if backend.x25519_supported(): + onion_key_line = _value('onion-key', entry) + onion_key_b64 = onion_key_line[5:] if onion_key_line.startswith('ntor ') else None + onion_key = X25519PublicKey.from_public_bytes(base64.b64decode(onion_key_b64)) + else: + onion_key = None
_, block_type, auth_key_cert = entry['auth-key'][0] auth_key_cert = Ed25519Certificate.parse(auth_key_cert) @@ -438,9 +442,12 @@ def _parse_v3_introduction_points(descriptor, entries): if block_type != 'ED25519 CERT': raise ValueError('Expected auth-key to have an ed25519 certificate, but was %s' % block_type)
- enc_key_line = _value('enc-key', entry) - enc_key_b64 = enc_key_line[5:] if enc_key_line.startswith('ntor ') else None - enc_key = X25519PublicKey.from_public_bytes(base64.b64decode(enc_key_b64)) + if backend.x25519_supported(): + enc_key_line = _value('enc-key', entry) + enc_key_b64 = enc_key_line[5:] if enc_key_line.startswith('ntor ') else None + enc_key = X25519PublicKey.from_public_bytes(base64.b64decode(enc_key_b64)) + else: + enc_key = None
_, block_type, enc_key_cert = entry['enc-key-cert'][0] enc_key_cert = Ed25519Certificate.parse(enc_key_cert) @@ -1050,18 +1057,21 @@ class HiddenServiceDescriptorV3(BaseHiddenServiceDescriptor): else: self._entries = entries
- # Verify the signature! - # First compute the body that was signed - descriptor_signing_key = self.signing_cert.certified_ed25519_key() - descriptor_body = raw_contents.split(b"signature")[0] # everything before the signature - signature_body = b"Tor onion service descriptor sig v3" + descriptor_body + from cryptography.hazmat.backends.openssl.backend import backend + + if backend.x25519_supported(): + # Verify the signature! + # First compute the body that was signed + descriptor_signing_key = self.signing_cert.certified_ed25519_key() + descriptor_body = raw_contents.split(b"signature")[0] # everything before the signature + signature_body = b"Tor onion service descriptor sig v3" + descriptor_body
- # Decode base64 signature - missing_padding = len(self.signature) % 4 - signature = base64.b64decode(self.signature + '=' * missing_padding) + # Decode base64 signature + missing_padding = len(self.signature) % 4 + signature = base64.b64decode(self.signature + '=' * missing_padding)
- # Verify signature - descriptor_signing_key.verify(signature, signature_body) + # Verify signature + descriptor_signing_key.verify(signature, signature_body)
def decrypt(self, onion_address): """ diff --git a/test/unit/descriptor/hidden_service_v3.py b/test/unit/descriptor/hidden_service_v3.py index b2a58fbc..dbd5220e 100644 --- a/test/unit/descriptor/hidden_service_v3.py +++ b/test/unit/descriptor/hidden_service_v3.py @@ -5,6 +5,7 @@ Unit tests for stem.descriptor.hidden_service for version 3. import functools import unittest
+from cryptography.hazmat.backends.openssl.backend import backend from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey from cryptography.hazmat.primitives import serialization @@ -142,6 +143,10 @@ class TestHiddenServiceDescriptorV3(unittest.TestCase): Check that we require the mandatory fields. """
+ if not backend.x25519_supported(): + self.skipTest('(requires openssl ed25519 support)') + return + line_to_attr = { 'hs-descriptor': 'version', 'descriptor-lifetime': 'lifetime', @@ -206,6 +211,9 @@ class TestHiddenServiceDescriptorV3(unittest.TestCase): elif not stem.prereq._is_sha3_available(): self.skipTest('(requires sha3 support)') return + elif not backend.x25519_supported(): + self.skipTest('(requires openssl ed25519 support)') + return
self.assertEqual(b'\x92\xe6\x80\xfaWU.}HL\x9d*>\xdbF\xfb\xc0v\xe5N\xa9\x0bw\xbb\x84\xe3\xe6\xd5e}R\xa1', HiddenServiceDescriptorV3._public_key_from_address(HS_ADDRESS)) self.assertRaisesWith(ValueError, "'boom.onion' isn't a valid hidden service v3 address", HiddenServiceDescriptorV3._public_key_from_address, 'boom') @@ -238,6 +246,11 @@ class TestHiddenServiceDescriptorV3(unittest.TestCase): this test generates is the data that onionbalance also has available when making onion service descriptors. """ + + if not backend.x25519_supported(): + self.skipTest('(requires openssl ed25519 support)') + return + # Build the service private_identity_key = Ed25519PrivateKey.from_private_bytes(b"a"*32) public_identity_key = private_identity_key.public_key()
tor-commits@lists.torproject.org