[tor-commits] [stem/master] Check for openssl ed25519 support

atagar at torproject.org atagar at torproject.org
Sun Nov 17 23:40:39 UTC 2019


commit f1312056f0a00132b19d247a4d0b53ff689b066d
Author: Damian Johnson <atagar at 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()





More information about the tor-commits mailing list