def generate(cls): from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed25519_supported(): raise UnsupportedAlgorithm( "ed25519 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM) return backend.ed25519_generate_key()
def from_private_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed25519_supported(): raise UnsupportedAlgorithm( "ed25519 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM) return backend.ed25519_load_private_bytes(data)
def from_private_bytes(cls, data): from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed25519_supported(): raise UnsupportedAlgorithm( "ed25519 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ) return backend.ed25519_load_private_bytes(data)
def generate(cls): from cryptography.hazmat.backends.openssl.backend import backend if not backend.ed25519_supported(): raise UnsupportedAlgorithm( "ed25519 is not supported by this version of OpenSSL.", _Reasons.UNSUPPORTED_PUBLIC_KEY_ALGORITHM ) return backend.ed25519_generate_key()
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_crypto_available(ed25519 = False): """ Checks if the cryptography functions we use are available. This is used for verifying relay descriptor signatures. :param bool ed25519: check for `ed25519 support <https://cryptography.io/en/latest/hazmat/primitives/asymmetric/ed25519/>`_, 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 from cryptography.hazmat.backends.openssl.backend import backend from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.serialization import load_der_public_key if not hasattr(rsa.RSAPrivateKey, 'sign'): 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: log.log_once('stem.prereq.is_crypto_available', log.INFO, CRYPTO_UNAVAILABLE) return False
class TestOCSPEdDSA(object): @pytest.mark.supported( only_if=lambda backend: backend.ed25519_supported(), skip_message="Requires OpenSSL with Ed25519 support / OCSP", ) def test_invalid_algorithm(self, backend): builder = ocsp.OCSPResponseBuilder() cert, issuer = _cert_and_issuer() private_key = ed25519.Ed25519PrivateKey.generate() root_cert, _ = _generate_root(private_key, None) current_time = datetime.datetime.utcnow().replace(microsecond=0) this_update = current_time - datetime.timedelta(days=1) next_update = this_update + datetime.timedelta(days=7) revoked_date = this_update - datetime.timedelta(days=300) builder = builder.responder_id(ocsp.OCSPResponderEncoding.NAME, root_cert).add_response( cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.REVOKED, this_update, next_update, revoked_date, x509.ReasonFlags.key_compromise, ) with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256()) @pytest.mark.supported( only_if=lambda backend: backend.ed25519_supported(), skip_message="Requires OpenSSL with Ed25519 support / OCSP", ) def test_sign_ed25519(self, backend): builder = ocsp.OCSPResponseBuilder() cert, issuer = _cert_and_issuer() private_key = ed25519.Ed25519PrivateKey.generate() root_cert, _ = _generate_root(private_key, None) current_time = datetime.datetime.utcnow().replace(microsecond=0) this_update = current_time - datetime.timedelta(days=1) next_update = this_update + datetime.timedelta(days=7) revoked_date = this_update - datetime.timedelta(days=300) builder = builder.responder_id(ocsp.OCSPResponderEncoding.NAME, root_cert).add_response( cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.REVOKED, this_update, next_update, revoked_date, x509.ReasonFlags.key_compromise, ) resp = builder.sign(private_key, None) assert resp.certificate_status == ocsp.OCSPCertStatus.REVOKED assert resp.revocation_time == revoked_date assert resp.revocation_reason is x509.ReasonFlags.key_compromise assert resp.this_update == this_update assert resp.next_update == next_update assert resp.signature_hash_algorithm is None assert ( resp.signature_algorithm_oid == x509.SignatureAlgorithmOID.ED25519) private_key.public_key().verify(resp.signature, resp.tbs_response_bytes) @pytest.mark.supported( only_if=lambda backend: backend.ed448_supported(), skip_message="Requires OpenSSL with Ed448 support / OCSP", ) def test_sign_ed448(self, backend): builder = ocsp.OCSPResponseBuilder() cert, issuer = _cert_and_issuer() private_key = ed448.Ed448PrivateKey.generate() root_cert, _ = _generate_root(private_key, None) current_time = datetime.datetime.utcnow().replace(microsecond=0) this_update = current_time - datetime.timedelta(days=1) next_update = this_update + datetime.timedelta(days=7) revoked_date = this_update - datetime.timedelta(days=300) builder = builder.responder_id(ocsp.OCSPResponderEncoding.NAME, root_cert).add_response( cert, issuer, hashes.SHA1(), ocsp.OCSPCertStatus.REVOKED, this_update, next_update, revoked_date, x509.ReasonFlags.key_compromise, ) resp = builder.sign(private_key, None) assert resp.certificate_status == ocsp.OCSPCertStatus.REVOKED assert resp.revocation_time == revoked_date assert resp.revocation_reason is x509.ReasonFlags.key_compromise assert resp.this_update == this_update assert resp.next_update == next_update assert resp.signature_hash_algorithm is None assert resp.signature_algorithm_oid == x509.SignatureAlgorithmOID.ED448 private_key.public_key().verify(resp.signature, resp.tbs_response_bytes)
import stem.util.system import stem.version import test import test.runner try: from cryptography.utils import int_from_bytes, int_to_bytes from cryptography.hazmat.backends import default_backend from cryptography.hazmat.backends.openssl.backend import backend from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives.serialization import load_der_public_key from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PublicKey if not hasattr(rsa.RSAPrivateKey, 'sign') or not hasattr( backend, 'ed25519_supported') or not backend.ed25519_supported(): raise ImportError() CRYPTOGRAPHY_AVAILABLE = True except ImportError: CRYPTOGRAPHY_AVAILABLE = False RAN_TESTS = [] def only_run_once(func): """ Skips the test if it has ran before. If it hasn't then flags it as being ran. This is useful to prevent lengthy tests that are independent of integ targets from being run repeatedly with ``RUN_ALL``. """