From 9c075b760105a2c1dfa9f9f1b6f986b35de8e390 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Tue, 6 Sep 2022 23:44:49 -0400 Subject: [PATCH] Remove deprecated support for x.509 signing with SHA1 and MD5 --- CHANGELOG.rst | 3 ++ src/cryptography/utils.py | 1 - src/rust/src/x509/oid.rs | 4 --- src/rust/src/x509/sign.rs | 47 -------------------------- tests/x509/test_x509.py | 69 +-------------------------------------- 5 files changed, 4 insertions(+), 120 deletions(-) diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 90bdc75fa3c7..b209f97028b0 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -20,6 +20,9 @@ Changelog and :meth:`~cryptography.hazmat.primitives.asymmetric.ec.EllipticCurvePublicKey.from_encoded_point` should be used instead. +* **BACKWARDS INCOMPATIBLE:** Support for using MD5 or SHA1 in + :class:`~cryptography.x509.CertificateBuilder` and + other X.509 builders has been removed. .. _v38-0-0: diff --git a/src/cryptography/utils.py b/src/cryptography/utils.py index 9c8189ee1d59..b3d7195b0efe 100644 --- a/src/cryptography/utils.py +++ b/src/cryptography/utils.py @@ -24,7 +24,6 @@ class CryptographyDeprecationWarning(UserWarning): DeprecatedIn35 = CryptographyDeprecationWarning DeprecatedIn36 = CryptographyDeprecationWarning DeprecatedIn37 = CryptographyDeprecationWarning -DeprecatedIn38 = CryptographyDeprecationWarning def _check_bytes(name: str, value: bytes) -> None: diff --git a/src/rust/src/x509/oid.rs b/src/rust/src/x509/oid.rs index 45cfc15db4ed..55477c60826a 100644 --- a/src/rust/src/x509/oid.rs +++ b/src/rust/src/x509/oid.rs @@ -43,7 +43,6 @@ pub(crate) const FRESHEST_CRL_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, pub(crate) const INHIBIT_ANY_POLICY_OID: asn1::ObjectIdentifier = asn1::oid!(2, 5, 29, 54); // Signing methods -pub(crate) const ECDSA_WITH_SHA1_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 10045, 4, 1); pub(crate) const ECDSA_WITH_SHA224_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 10045, 4, 3, 1); pub(crate) const ECDSA_WITH_SHA256_OID: asn1::ObjectIdentifier = @@ -61,8 +60,6 @@ pub(crate) const ECDSA_WITH_SHA3_384_OID: asn1::ObjectIdentifier = pub(crate) const ECDSA_WITH_SHA3_512_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 12); -pub(crate) const RSA_WITH_MD5_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 1, 4); -pub(crate) const RSA_WITH_SHA1_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 1, 5); pub(crate) const RSA_WITH_SHA224_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 113549, 1, 1, 14); pub(crate) const RSA_WITH_SHA256_OID: asn1::ObjectIdentifier = @@ -80,7 +77,6 @@ pub(crate) const RSA_WITH_SHA3_384_OID: asn1::ObjectIdentifier = pub(crate) const RSA_WITH_SHA3_512_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 16); -pub(crate) const DSA_WITH_SHA1_OID: asn1::ObjectIdentifier = asn1::oid!(1, 2, 840, 10040, 4, 3); pub(crate) const DSA_WITH_SHA224_OID: asn1::ObjectIdentifier = asn1::oid!(2, 16, 840, 1, 101, 3, 4, 3, 1); pub(crate) const DSA_WITH_SHA256_OID: asn1::ObjectIdentifier = diff --git a/src/rust/src/x509/sign.rs b/src/rust/src/x509/sign.rs index 4d9157505b5c..37860c3a5c7c 100644 --- a/src/rust/src/x509/sign.rs +++ b/src/rust/src/x509/sign.rs @@ -24,8 +24,6 @@ enum KeyType { enum HashType { None, - Md5, - Sha1, Sha224, Sha256, Sha384, @@ -97,32 +95,6 @@ fn identify_hash_type( .getattr(crate::intern!(py, "name"))? .extract()? { - "md5" => { - let cryptography_warning = py - .import("cryptography.utils")? - .getattr(crate::intern!(py, "DeprecatedIn38"))?; - pyo3::PyErr::warn( - py, - cryptography_warning, - "MD5 signatures are deprecated and support for them will be removed in the next version.", - 1 - )?; - - Ok(HashType::Md5) - } - "sha1" => { - let cryptography_warning = py - .import("cryptography.utils")? - .getattr(crate::intern!(py, "DeprecatedIn38"))?; - pyo3::PyErr::warn( - py, - cryptography_warning, - "SHA1 signatures are deprecated and support for them will be removed in the next version.", - 1 - )?; - - Ok(HashType::Sha1) - } "sha224" => Ok(HashType::Sha224), "sha256" => Ok(HashType::Sha256), "sha384" => Ok(HashType::Sha384), @@ -161,10 +133,6 @@ pub(crate) fn compute_signature_algorithm<'p>( )) } - (KeyType::Ec, HashType::Sha1) => Ok(x509::AlgorithmIdentifier { - oid: (oid::ECDSA_WITH_SHA1_OID).clone(), - params: None, - }), (KeyType::Ec, HashType::Sha224) => Ok(x509::AlgorithmIdentifier { oid: (oid::ECDSA_WITH_SHA224_OID).clone(), params: None, @@ -198,14 +166,6 @@ pub(crate) fn compute_signature_algorithm<'p>( params: None, }), - (KeyType::Rsa, HashType::Md5) => Ok(x509::AlgorithmIdentifier { - oid: (oid::RSA_WITH_MD5_OID).clone(), - params: Some(*NULL_TLV), - }), - (KeyType::Rsa, HashType::Sha1) => Ok(x509::AlgorithmIdentifier { - oid: (oid::RSA_WITH_SHA1_OID).clone(), - params: Some(*NULL_TLV), - }), (KeyType::Rsa, HashType::Sha224) => Ok(x509::AlgorithmIdentifier { oid: (oid::RSA_WITH_SHA224_OID).clone(), params: Some(*NULL_TLV), @@ -239,10 +199,6 @@ pub(crate) fn compute_signature_algorithm<'p>( params: Some(*NULL_TLV), }), - (KeyType::Dsa, HashType::Sha1) => Ok(x509::AlgorithmIdentifier { - oid: (oid::DSA_WITH_SHA1_OID).clone(), - params: None, - }), (KeyType::Dsa, HashType::Sha224) => Ok(x509::AlgorithmIdentifier { oid: (oid::DSA_WITH_SHA224_OID).clone(), params: None, @@ -269,9 +225,6 @@ pub(crate) fn compute_signature_algorithm<'p>( (_, HashType::None) => Err(pyo3::exceptions::PyTypeError::new_err( "Algorithm must be a registered hash algorithm, not None.", )), - (_, HashType::Md5) => Err(pyo3::exceptions::PyValueError::new_err( - "MD5 hash algorithm is only supported with RSA keys", - )), } } diff --git a/tests/x509/test_x509.py b/tests/x509/test_x509.py index 55ecdfb01784..e89627ac0531 100644 --- a/tests/x509/test_x509.py +++ b/tests/x509/test_x509.py @@ -1856,7 +1856,6 @@ def test_hash(self, backend): @pytest.mark.parametrize( ("hashalg", "hashalg_oid"), [ - (hashes.SHA1, x509.SignatureAlgorithmOID.RSA_WITH_SHA1), (hashes.SHA224, x509.SignatureAlgorithmOID.RSA_WITH_SHA224), (hashes.SHA256, x509.SignatureAlgorithmOID.RSA_WITH_SHA256), (hashes.SHA384, x509.SignatureAlgorithmOID.RSA_WITH_SHA384), @@ -2067,7 +2066,7 @@ def test_checks_for_unsupported_extensions(self, backend): ) with pytest.raises(NotImplementedError): - builder.sign(private_key, hashes.SHA1(), backend) + builder.sign(private_key, hashes.SHA256(), backend) def test_encode_nonstandard_aia(self, backend): private_key = RSA_KEY_2048.private_key(backend) @@ -2640,28 +2639,6 @@ def test_sign_with_unsupported_hash_ed448(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.MD5()), - skip_message="Requires OpenSSL with MD5 support", - ) - def test_sign_rsa_with_md5(self, backend): - private_key = RSA_KEY_2048.private_key(backend) - builder = x509.CertificateBuilder() - builder = ( - builder.subject_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .issuer_name( - x509.Name([x509.NameAttribute(NameOID.COUNTRY_NAME, "US")]) - ) - .serial_number(1) - .public_key(private_key.public_key()) - .not_valid_before(datetime.datetime(2002, 1, 1, 12, 1)) - .not_valid_after(datetime.datetime(2032, 1, 1, 12, 1)) - ) - cert = builder.sign(private_key, hashes.MD5(), backend) - assert isinstance(cert.signature_hash_algorithm, hashes.MD5) - @pytest.mark.supported( only_if=lambda backend: backend.hash_supported(hashes.MD5()), skip_message="Requires OpenSSL with MD5 support", @@ -2728,7 +2705,6 @@ def test_sign_ec_with_md5(self, backend): @pytest.mark.parametrize( ("hashalg", "hashalg_oid"), [ - (hashes.SHA1, x509.SignatureAlgorithmOID.DSA_WITH_SHA1), (hashes.SHA224, x509.SignatureAlgorithmOID.DSA_WITH_SHA224), (hashes.SHA256, x509.SignatureAlgorithmOID.DSA_WITH_SHA256), (hashes.SHA384, x509.SignatureAlgorithmOID.DSA_WITH_SHA384), @@ -2791,7 +2767,6 @@ def test_build_cert_with_dsa_private_key( @pytest.mark.parametrize( ("hashalg", "hashalg_oid"), [ - (hashes.SHA1, x509.SignatureAlgorithmOID.ECDSA_WITH_SHA1), (hashes.SHA224, x509.SignatureAlgorithmOID.ECDSA_WITH_SHA224), (hashes.SHA256, x509.SignatureAlgorithmOID.ECDSA_WITH_SHA256), (hashes.SHA384, x509.SignatureAlgorithmOID.ECDSA_WITH_SHA384), @@ -3753,48 +3728,6 @@ def test_request_with_unsupported_hash_ed448(self, backend): with pytest.raises(ValueError): builder.sign(private_key, hashes.SHA256(), backend) - @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.MD5()), - skip_message="Requires OpenSSL with MD5 support", - ) - def test_sign_rsa_with_md5(self, backend): - private_key = RSA_KEY_2048.private_key(backend) - - builder = x509.CertificateSigningRequestBuilder().subject_name( - x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA")]) - ) - request = builder.sign(private_key, hashes.MD5(), backend) - assert isinstance(request.signature_hash_algorithm, hashes.MD5) - - @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.MD5()), - skip_message="Requires OpenSSL with MD5 support", - ) - @pytest.mark.supported( - only_if=lambda backend: backend.dsa_supported(), - skip_message="Does not support DSA.", - ) - def test_sign_dsa_with_md5(self, backend): - private_key = DSA_KEY_2048.private_key(backend) - builder = x509.CertificateSigningRequestBuilder().subject_name( - x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA")]) - ) - with pytest.raises(ValueError): - builder.sign(private_key, hashes.MD5(), backend) - - @pytest.mark.supported( - only_if=lambda backend: backend.hash_supported(hashes.MD5()), - skip_message="Requires OpenSSL with MD5 support", - ) - def test_sign_ec_with_md5(self, backend): - _skip_curve_unsupported(backend, ec.SECP256R1()) - private_key = EC_KEY_SECP256R1.private_key(backend) - builder = x509.CertificateSigningRequestBuilder().subject_name( - x509.Name([x509.NameAttribute(NameOID.ORGANIZATION_NAME, "PyCA")]) - ) - with pytest.raises(ValueError): - builder.sign(private_key, hashes.MD5(), backend) - def test_no_subject_name(self, backend): private_key = RSA_KEY_2048.private_key(backend)