[tor-commits] [stem/master] Remove _is_crypto_ed25519_supported() helper

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


commit 30156ada4979eb02fa06236066cc94d73c75f9ce
Author: Damian Johnson <atagar at torproject.org>
Date:   Fri Oct 18 12:33:34 2019 -0700

    Remove _is_crypto_ed25519_supported() helper
    
    We have a couple checks that are unpleasantly similar...
    
      * "is_crypto_available(ed25519 = True)" checks if the cryptography module
        has ed25519 support (ie. if cryptograhy itself is modern enough)
    
      * "_is_crypto_ed25519_supported()" checks if OpenSSL has ed25519 support
    
    This is confusing, so combining these into a single "is ed25519 fully
    supported?" check. This potentially makes our checks stricter (ie. we do
    less when one check is true, and the other is false) but this isn't worth
    the additional confusion.
---
 stem/descriptor/certificate.py            |  2 +-
 stem/descriptor/hidden_service.py         |  9 +++-----
 stem/descriptor/server_descriptor.py      |  2 +-
 stem/prereq.py                            | 34 +++++++++----------------------
 test/require.py                           |  2 +-
 test/unit/descriptor/hidden_service_v3.py | 12 ++++-------
 6 files changed, 20 insertions(+), 41 deletions(-)

diff --git a/stem/descriptor/certificate.py b/stem/descriptor/certificate.py
index c0897b13..90476576 100644
--- a/stem/descriptor/certificate.py
+++ b/stem/descriptor/certificate.py
@@ -290,7 +290,7 @@ class Ed25519CertificateV1(Ed25519Certificate):
       * **ImportError** if cryptography module or ed25519 support unavailable
     """
 
-    if not stem.prereq._is_crypto_ed25519_supported():
+    if not stem.prereq.is_crypto_available(ed25519 = True):
       raise ImportError('Certificate validation requires the cryptography module and ed25519 support')
 
     if isinstance(descriptor, stem.descriptor.server_descriptor.RelayDescriptor):
diff --git a/stem/descriptor/hidden_service.py b/stem/descriptor/hidden_service.py
index 1a2ce69c..2037cc0e 100644
--- a/stem/descriptor/hidden_service.py
+++ b/stem/descriptor/hidden_service.py
@@ -188,8 +188,6 @@ class IntroductionPointV3(object):
     descriptor_signing_key is provided.
     """
 
-    from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
-
     # if not link_specifiers or not onion_key or not enc_key:
     #   raise ValueError('Introduction point missing essential keys')
 
@@ -197,7 +195,8 @@ class IntroductionPointV3(object):
       raise ValueError('Either auth key or auth key cert needs to be provided')
 
     # If we have an auth key cert but not an auth key, extract the key
-    if auth_key_cert and not auth_key:
+    if auth_key_cert and not auth_key and stem.prereq.is_crypto_available(ed25519 = True):
+      from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
       auth_key = Ed25519PublicKey.from_public_bytes(auth_key_cert.key)
 
     self.link_specifiers = link_specifiers
@@ -1031,8 +1030,6 @@ class HiddenServiceDescriptorV3(BaseHiddenServiceDescriptor):
 
   @classmethod
   def create(cls, attr = None, exclude = (), validate = True, sign = False):
-    # Create a string-representation of the descriptor and then parse it
-    # immediately to create an object.
     return cls(cls.content(attr, exclude, sign), validate = validate, skip_crypto_validation = not sign)
 
   def __init__(self, raw_contents, validate = False):
@@ -1055,7 +1052,7 @@ class HiddenServiceDescriptorV3(BaseHiddenServiceDescriptor):
 
       self._parse(entries, validate)
 
-      if self.signing_cert:
+      if self.signing_cert and stem.prereq.is_crypto_available(ed25519 = True):
         self.signing_cert.validate(self)
     else:
       self._entries = entries
diff --git a/stem/descriptor/server_descriptor.py b/stem/descriptor/server_descriptor.py
index ebadcde2..a2be8483 100644
--- a/stem/descriptor/server_descriptor.py
+++ b/stem/descriptor/server_descriptor.py
@@ -858,7 +858,7 @@ class RelayDescriptor(ServerDescriptor):
           if onion_key_crosscert_digest != self._onion_key_crosscert_digest():
             raise ValueError('Decrypted onion-key-crosscert digest does not match local digest (calculated: %s, local: %s)' % (onion_key_crosscert_digest, self._onion_key_crosscert_digest()))
 
-      if stem.prereq._is_crypto_ed25519_supported() and self.certificate:
+      if stem.prereq.is_crypto_available(ed25519 = True) and self.certificate:
         self.certificate.validate(self)
 
   @classmethod
diff --git a/stem/prereq.py b/stem/prereq.py
index e8218e7f..40c2f006 100644
--- a/stem/prereq.py
+++ b/stem/prereq.py
@@ -127,12 +127,14 @@ def is_crypto_available(ed25519 = False):
 
   :param bool ed25519: check for `ed25519 support
     <https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ed25519/>`_,
-    which was added in version 2.6
+    which requires both cryptography version 2.6 and OpenSSL support
 
   :returns: **True** if we can use the cryptography module and **False**
     otherwise
   """
 
+  from stem.util import log
+
   try:
     from cryptography.utils import int_from_bytes, int_to_bytes
     from cryptography.hazmat.backends import default_backend
@@ -145,11 +147,17 @@ def is_crypto_available(ed25519 = False):
       raise ImportError()
 
     if ed25519:
+      # The following import confirms cryptography support (ie. version 2.6+),
+      # whereas ed25519_supported() checks for OpenSSL bindings.
+
       from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey
 
+      if not hasattr(backend, 'ed25519_supported') or not backend.ed25519_supported():
+        log.log_once('stem.prereq._is_crypto_ed25519_supported', log.INFO, ED25519_UNSUPPORTED)
+        return False
+
     return True
   except ImportError:
-    from stem.util import log
     log.log_once('stem.prereq.is_crypto_available', log.INFO, CRYPTO_UNAVAILABLE)
     return False
 
@@ -253,28 +261,6 @@ def _is_lru_cache_available():
     return hasattr(functools, 'lru_cache')
 
 
-def _is_crypto_ed25519_supported():
-  """
-  Checks if ed25519 is supported by current versions of the cryptography
-  package and OpenSSL. This is used for verifying ed25519 certificates in relay
-  descriptor signatures.
-
-  :returns: **True** if ed25519 is supported and **False** otherwise
-  """
-
-  if not is_crypto_available():
-    return False
-
-  from stem.util import log
-  from cryptography.hazmat.backends.openssl.backend import backend
-
-  if hasattr(backend, 'ed25519_supported') and backend.ed25519_supported():
-    return True
-  else:
-    log.log_once('stem.prereq._is_crypto_ed25519_supported', log.INFO, ED25519_UNSUPPORTED)
-    return False
-
-
 def _is_sha3_available():
   """
   Check if hashlib has sha3 support. This requires Python 3.6+ *or* the `pysha3
diff --git a/test/require.py b/test/require.py
index 1117ea1e..af33359f 100644
--- a/test/require.py
+++ b/test/require.py
@@ -98,7 +98,7 @@ def version(req_version):
 
 
 cryptography = needs(stem.prereq.is_crypto_available, 'requires cryptography')
-ed25519_support = needs(stem.prereq._is_crypto_ed25519_supported, 'requires ed25519 support')
+ed25519_support = needs(lambda: stem.prereq.is_crypto_available(ed25519 = True), 'requires ed25519 support')
 proc = needs(stem.util.proc.is_available, 'proc unavailable')
 controller = needs(_can_access_controller, 'no connection')
 ptrace = needs(_can_ptrace, 'DisableDebuggerAttachment is set')
diff --git a/test/unit/descriptor/hidden_service_v3.py b/test/unit/descriptor/hidden_service_v3.py
index b3a26931..e668b04f 100644
--- a/test/unit/descriptor/hidden_service_v3.py
+++ b/test/unit/descriptor/hidden_service_v3.py
@@ -5,7 +5,6 @@ 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
@@ -148,8 +147,8 @@ class TestHiddenServiceDescriptorV3(unittest.TestCase):
     Check that we require the mandatory fields.
     """
 
-    if not backend.x25519_supported():
-      self.skipTest('(requires openssl ed25519 support)')
+    if not stem.prereq.is_crypto_available(ed25519 = True):
+      self.skipTest('(requires cryptography ed25519 support)')
       return
 
     line_to_attr = {
@@ -216,9 +215,6 @@ 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')
@@ -252,8 +248,8 @@ class TestHiddenServiceDescriptorV3(unittest.TestCase):
     making onion service descriptors.
     """
 
-    if not backend.x25519_supported():
-      self.skipTest('(requires openssl ed25519 support)')
+    if not stem.prereq.is_crypto_available(ed25519 = True):
+      self.skipTest('(requires cryptography ed25519 support)')
       return
 
     # Build the service





More information about the tor-commits mailing list