diff --git a/disable-RSA-PKCS-1v1.5-padding-to-fix-CVE-2023-50782.patch b/disable-RSA-PKCS-1v1.5-padding-to-fix-CVE-2023-50782.patch new file mode 100644 index 0000000000000000000000000000000000000000..91953fd86353384cb17deb51145070e327f3702a --- /dev/null +++ b/disable-RSA-PKCS-1v1.5-padding-to-fix-CVE-2023-50782.patch @@ -0,0 +1,479 @@ +From fe6fe6fac2671a37eba40b4c6b2e8f356605761d Mon Sep 17 00:00:00 2001 +From: shixuantong +Date: Tue, 29 Jul 2025 09:55:25 +0800 +Subject: [PATCH] disable RSA PKCS#1v1.5 padding to fix CVE-2023-50782 + +--- + src/rust/src/backend/rsa.rs | 6 +- + tests/hazmat/primitives/test_pkcs7.py | 304 +++++++++++++------------- + tests/hazmat/primitives/test_rsa.py | 16 +- + 3 files changed, 172 insertions(+), 154 deletions(-) + +diff --git a/src/rust/src/backend/rsa.rs b/src/rust/src/backend/rsa.rs +index b490e1c..7e65ca2 100644 +--- a/src/rust/src/backend/rsa.rs ++++ b/src/rust/src/backend/rsa.rs +@@ -92,7 +92,11 @@ fn setup_encryption_ctx( + } + + let padding_enum = if padding.is_instance(&types::PKCS1V15.get(py)?)? { +- openssl::rsa::Padding::PKCS1 ++ return Err(CryptographyError::from( ++ pyo3::exceptions::PyValueError::new_err( ++ "RSA PKCS#1v1.5 has security problems and it has been banned.", ++ ), ++ )); + } else if padding.is_instance(&types::OAEP.get(py)?)? { + if !padding + .getattr(pyo3::intern!(py, "_mgf"))? +diff --git a/tests/hazmat/primitives/test_pkcs7.py b/tests/hazmat/primitives/test_pkcs7.py +index 1496a23..ec691de 100644 +--- a/tests/hazmat/primitives/test_pkcs7.py ++++ b/tests/hazmat/primitives/test_pkcs7.py +@@ -982,45 +982,46 @@ class TestPKCS7EnvelopeBuilder: + builder = ( + pkcs7.PKCS7EnvelopeBuilder().set_data(data).add_recipient(cert) + ) +- enveloped = builder.encrypt(serialization.Encoding.SMIME, options) +- assert b"MIME-Version: 1.0\n" in enveloped +- assert b"Content-Transfer-Encoding: base64\n" in enveloped +- message = email.parser.BytesParser().parsebytes(enveloped) +- assert message.get_content_disposition() == "attachment" +- assert message.get_filename() == "smime.p7m" +- assert message.get_content_type() == "application/pkcs7-mime" +- assert message.get_param("smime-type") == "enveloped-data" +- assert message.get_param("name") == "smime.p7m" +- +- payload = message.get_payload(decode=True) +- assert isinstance(payload, bytes) +- +- # We want to know if we've serialized something that has the parameters +- # we expect, so we match on specific byte strings of OIDs & DER values. +- # OID 2.16.840.1.101.3.4.1.2 (aes128-CBC) +- assert b"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x01\x02" in payload +- # OID 1.2.840.113549.1.1.1 (rsaEncryption (PKCS #1)) +- assert b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01" in payload +- # cryptography CA (the recipient's Common Name) +- assert ( +- b"\x0c\x0f\x63\x72\x79\x70\x74\x6f\x67\x72\x61\x70\x68\x79" +- b"\x20\x43\x41" +- ) in payload ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ enveloped = builder.encrypt(serialization.Encoding.SMIME, options) ++ assert b"MIME-Version: 1.0\n" in enveloped ++ assert b"Content-Transfer-Encoding: base64\n" in enveloped ++ message = email.parser.BytesParser().parsebytes(enveloped) ++ assert message.get_content_disposition() == "attachment" ++ assert message.get_filename() == "smime.p7m" ++ assert message.get_content_type() == "application/pkcs7-mime" ++ assert message.get_param("smime-type") == "enveloped-data" ++ assert message.get_param("name") == "smime.p7m" ++ ++ payload = message.get_payload(decode=True) ++ assert isinstance(payload, bytes) ++ ++ # We want to know if we've serialized something that has the parameters ++ # we expect, so we match on specific byte strings of OIDs & DER values. ++ # OID 2.16.840.1.101.3.4.1.2 (aes128-CBC) ++ assert b"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x01\x02" in payload ++ # OID 1.2.840.113549.1.1.1 (rsaEncryption (PKCS #1)) ++ assert b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01" in payload ++ # cryptography CA (the recipient's Common Name) ++ assert ( ++ b"\x0c\x0f\x63\x72\x79\x70\x74\x6f\x67\x72\x61\x70\x68\x79" ++ b"\x20\x43\x41" ++ ) in payload + +- decrypted_bytes = pkcs7.pkcs7_decrypt_smime( +- enveloped, +- cert, +- private_key, +- [o for o in options if o != pkcs7.PKCS7Options.Binary], +- ) ++ decrypted_bytes = pkcs7.pkcs7_decrypt_smime( ++ enveloped, ++ cert, ++ private_key, ++ [o for o in options if o != pkcs7.PKCS7Options.Binary], ++ ) + +- # New lines are canonicalized to '\r\n' when not using Binary +- expected_data = ( +- data +- if pkcs7.PKCS7Options.Binary in options +- else data.replace(b"\n", b"\r\n") +- ) +- assert decrypted_bytes == expected_data ++ # New lines are canonicalized to '\r\n' when not using Binary ++ expected_data = ( ++ data ++ if pkcs7.PKCS7Options.Binary in options ++ else data.replace(b"\n", b"\r\n") ++ ) ++ assert decrypted_bytes == expected_data + + @pytest.mark.parametrize( + "options", +@@ -1035,33 +1036,34 @@ class TestPKCS7EnvelopeBuilder: + builder = ( + pkcs7.PKCS7EnvelopeBuilder().set_data(data).add_recipient(cert) + ) +- enveloped = builder.encrypt(serialization.Encoding.DER, options) ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ enveloped = builder.encrypt(serialization.Encoding.DER, options) + +- # We want to know if we've serialized something that has the parameters +- # we expect, so we match on specific byte strings of OIDs & DER values. +- # OID 2.16.840.1.101.3.4.1.2 (aes128-CBC) +- assert b"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x01\x02" in enveloped +- # OID 1.2.840.113549.1.1.1 (rsaEncryption (PKCS #1)) +- assert b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01" in enveloped +- # cryptography CA (the recipient's Common Name) +- assert ( +- b"\x0c\x0f\x63\x72\x79\x70\x74\x6f\x67\x72\x61\x70\x68\x79" +- b"\x20\x43\x41" +- ) in enveloped ++ # We want to know if we've serialized something that has the parameters ++ # we expect, so we match on specific byte strings of OIDs & DER values. ++ # OID 2.16.840.1.101.3.4.1.2 (aes128-CBC) ++ assert b"\x06\x09\x60\x86\x48\x01\x65\x03\x04\x01\x02" in enveloped ++ # OID 1.2.840.113549.1.1.1 (rsaEncryption (PKCS #1)) ++ assert b"\x06\x09\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01" in enveloped ++ # cryptography CA (the recipient's Common Name) ++ assert ( ++ b"\x0c\x0f\x63\x72\x79\x70\x74\x6f\x67\x72\x61\x70\x68\x79" ++ b"\x20\x43\x41" ++ ) in enveloped + +- decrypted_bytes = pkcs7.pkcs7_decrypt_der( +- enveloped, +- cert, +- private_key, +- [o for o in options if o != pkcs7.PKCS7Options.Binary], +- ) +- # New lines are canonicalized to '\r\n' when not using Binary +- expected_data = ( +- data +- if pkcs7.PKCS7Options.Binary in options +- else data.replace(b"\n", b"\r\n") +- ) +- assert decrypted_bytes == expected_data ++ decrypted_bytes = pkcs7.pkcs7_decrypt_der( ++ enveloped, ++ cert, ++ private_key, ++ [o for o in options if o != pkcs7.PKCS7Options.Binary], ++ ) ++ # New lines are canonicalized to '\r\n' when not using Binary ++ expected_data = ( ++ data ++ if pkcs7.PKCS7Options.Binary in options ++ else data.replace(b"\n", b"\r\n") ++ ) ++ assert decrypted_bytes == expected_data + + @pytest.mark.parametrize( + "options", +@@ -1076,21 +1078,22 @@ class TestPKCS7EnvelopeBuilder: + builder = ( + pkcs7.PKCS7EnvelopeBuilder().set_data(data).add_recipient(cert) + ) +- enveloped = builder.encrypt(serialization.Encoding.PEM, options) +- decrypted_bytes = pkcs7.pkcs7_decrypt_pem( +- enveloped, +- cert, +- private_key, +- [o for o in options if o != pkcs7.PKCS7Options.Binary], +- ) ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ enveloped = builder.encrypt(serialization.Encoding.PEM, options) ++ decrypted_bytes = pkcs7.pkcs7_decrypt_pem( ++ enveloped, ++ cert, ++ private_key, ++ [o for o in options if o != pkcs7.PKCS7Options.Binary], ++ ) + +- # New lines are canonicalized to '\r\n' when not using Binary +- expected_data = ( +- data +- if pkcs7.PKCS7Options.Binary in options +- else data.replace(b"\n", b"\r\n") +- ) +- assert decrypted_bytes == expected_data ++ # New lines are canonicalized to '\r\n' when not using Binary ++ expected_data = ( ++ data ++ if pkcs7.PKCS7Options.Binary in options ++ else data.replace(b"\n", b"\r\n") ++ ) ++ assert decrypted_bytes == expected_data + + def test_smime_encrypt_multiple_recipients(self, backend): + data = b"hello world\n" +@@ -1101,13 +1104,14 @@ class TestPKCS7EnvelopeBuilder: + .add_recipient(cert) + .add_recipient(cert) + ) +- enveloped = builder.encrypt(serialization.Encoding.DER, []) +- # cryptography CA (the recipient's Common Name) +- common_name_bytes = ( +- b"\x0c\x0f\x63\x72\x79\x70\x74\x6f\x67\x72\x61" +- b"\x70\x68\x79\x20\x43\x41" +- ) +- assert enveloped.count(common_name_bytes) == 2 ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ enveloped = builder.encrypt(serialization.Encoding.DER, []) ++ # cryptography CA (the recipient's Common Name) ++ common_name_bytes = ( ++ b"\x0c\x0f\x63\x72\x79\x70\x74\x6f\x67\x72\x61" ++ b"\x70\x68\x79\x20\x43\x41" ++ ) ++ assert enveloped.count(common_name_bytes) == 2 + + + @pytest.mark.supported( +@@ -1170,14 +1174,15 @@ class TestPKCS7Decrypt: + .set_data(data) + .add_recipient(certificate) + ) +- enveloped = builder.encrypt(serialization.Encoding.DER, options) ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ enveloped = builder.encrypt(serialization.Encoding.DER, options) + +- # Test decryption: new lines are canonicalized to '\r\n' when +- # encryption has no Binary option +- decrypted = pkcs7.pkcs7_decrypt_der( +- enveloped, certificate, private_key, options +- ) +- assert decrypted == data.replace(b"\n", b"\r\n") ++ # Test decryption: new lines are canonicalized to '\r\n' when ++ # encryption has no Binary option ++ decrypted = pkcs7.pkcs7_decrypt_der( ++ enveloped, certificate, private_key, options ++ ) ++ assert decrypted == data.replace(b"\n", b"\r\n") + + def test_pkcs7_decrypt_aes_256_cbc_encrypted_content( + self, backend, data, certificate, private_key +@@ -1189,14 +1194,15 @@ class TestPKCS7Decrypt: + .set_content_encryption_algorithm(algorithms.AES256) + .add_recipient(certificate) + ) +- enveloped = builder.encrypt(serialization.Encoding.PEM, []) ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ enveloped = builder.encrypt(serialization.Encoding.PEM, []) + +- # Test decryption: new lines are canonicalized to '\r\n' when +- # encryption has no Binary option +- decrypted = pkcs7.pkcs7_decrypt_pem( +- enveloped, certificate, private_key, [] +- ) +- assert decrypted == data.replace(b"\n", b"\r\n") ++ # Test decryption: new lines are canonicalized to '\r\n' when ++ # encryption has no Binary option ++ decrypted = pkcs7.pkcs7_decrypt_pem( ++ enveloped, certificate, private_key, [] ++ ) ++ assert decrypted == data.replace(b"\n", b"\r\n") + + @pytest.mark.parametrize( + "header", +@@ -1219,15 +1225,16 @@ class TestPKCS7Decrypt: + .set_data(data) + .add_recipient(certificate) + ) +- enveloped = builder.encrypt( +- serialization.Encoding.DER, [pkcs7.PKCS7Options.Binary] +- ) ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ enveloped = builder.encrypt( ++ serialization.Encoding.DER, [pkcs7.PKCS7Options.Binary] ++ ) + +- # Test decryption with text option +- decrypted = pkcs7.pkcs7_decrypt_der( +- enveloped, certificate, private_key, [pkcs7.PKCS7Options.Text] +- ) +- assert decrypted == base_data.encode() ++ # Test decryption with text option ++ decrypted = pkcs7.pkcs7_decrypt_der( ++ enveloped, certificate, private_key, [pkcs7.PKCS7Options.Text] ++ ) ++ assert decrypted == base_data.encode() + + @pytest.mark.parametrize("options", [[], [pkcs7.PKCS7Options.Text]]) + def test_pkcs7_decrypt_pem( +@@ -1239,14 +1246,15 @@ class TestPKCS7Decrypt: + .set_data(data) + .add_recipient(certificate) + ) +- enveloped = builder.encrypt(serialization.Encoding.PEM, options) ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ enveloped = builder.encrypt(serialization.Encoding.PEM, options) + +- # Test decryption: new lines are canonicalized to '\r\n' when +- # encryption has no Binary option +- decrypted = pkcs7.pkcs7_decrypt_pem( +- enveloped, certificate, private_key, options +- ) +- assert decrypted == data.replace(b"\n", b"\r\n") ++ # Test decryption: new lines are canonicalized to '\r\n' when ++ # encryption has no Binary option ++ decrypted = pkcs7.pkcs7_decrypt_pem( ++ enveloped, certificate, private_key, options ++ ) ++ assert decrypted == data.replace(b"\n", b"\r\n") + + def test_pkcs7_decrypt_pem_with_wrong_tag( + self, backend, data, certificate, private_key +@@ -1269,13 +1277,14 @@ class TestPKCS7Decrypt: + .set_data(data) + .add_recipient(certificate) + ) +- enveloped = builder.encrypt(serialization.Encoding.SMIME, options) ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ enveloped = builder.encrypt(serialization.Encoding.SMIME, options) + +- # Test decryption +- decrypted = pkcs7.pkcs7_decrypt_smime( +- enveloped, certificate, private_key, options +- ) +- assert decrypted == data.replace(b"\n", b"\r\n") ++ # Test decryption ++ decrypted = pkcs7.pkcs7_decrypt_smime( ++ enveloped, certificate, private_key, options ++ ) ++ assert decrypted == data.replace(b"\n", b"\r\n") + + def test_pkcs7_decrypt_no_encrypted_content( + self, backend, data, certificate, private_key +@@ -1299,13 +1308,14 @@ class TestPKCS7Decrypt: + .set_data(data) + .add_recipient(certificate) + ) +- enveloped = builder.encrypt(serialization.Encoding.DER, []) ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ enveloped = builder.encrypt(serialization.Encoding.DER, []) + +- # Test decryption with text option +- with pytest.raises(ValueError): +- pkcs7.pkcs7_decrypt_der( +- enveloped, certificate, private_key, [pkcs7.PKCS7Options.Text] +- ) ++ # Test decryption with text option ++ with pytest.raises(ValueError): ++ pkcs7.pkcs7_decrypt_der( ++ enveloped, certificate, private_key, [pkcs7.PKCS7Options.Text] ++ ) + + def test_pkcs7_decrypt_text_html_content_type( + self, backend, certificate, private_key +@@ -1317,16 +1327,17 @@ class TestPKCS7Decrypt: + .set_data(data) + .add_recipient(certificate) + ) +- enveloped = builder.encrypt( +- serialization.Encoding.DER, [pkcs7.PKCS7Options.Binary] +- ) +- +- # Test decryption with text option +- with pytest.raises(ValueError): +- pkcs7.pkcs7_decrypt_der( +- enveloped, certificate, private_key, [pkcs7.PKCS7Options.Text] ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ enveloped = builder.encrypt( ++ serialization.Encoding.DER, [pkcs7.PKCS7Options.Binary] + ) + ++ # Test decryption with text option ++ with pytest.raises(ValueError): ++ pkcs7.pkcs7_decrypt_der( ++ enveloped, certificate, private_key, [pkcs7.PKCS7Options.Text] ++ ) ++ + def test_smime_decrypt_no_recipient_match( + self, backend, data, certificate, rsa_key_2048: rsa.RSAPrivateKey + ): +@@ -1336,21 +1347,22 @@ class TestPKCS7Decrypt: + .set_data(data) + .add_recipient(certificate) + ) +- enveloped = builder.encrypt(serialization.Encoding.DER, []) ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ enveloped = builder.encrypt(serialization.Encoding.DER, []) + +- # Prepare another RSA chain +- another_private_key = RSA_KEY_2048_ALT.private_key( +- unsafe_skip_rsa_key_validation=True +- ) +- _, another_cert = _generate_ca_and_leaf( +- rsa_key_2048, another_private_key +- ) +- +- # Test decryption with another RSA chain +- with pytest.raises(ValueError): +- pkcs7.pkcs7_decrypt_der( +- enveloped, another_cert, another_private_key, [] ++ # Prepare another RSA chain ++ another_private_key = RSA_KEY_2048_ALT.private_key( ++ unsafe_skip_rsa_key_validation=True + ) ++ _, another_cert = _generate_ca_and_leaf( ++ rsa_key_2048, another_private_key ++ ) ++ ++ # Test decryption with another RSA chain ++ with pytest.raises(ValueError): ++ pkcs7.pkcs7_decrypt_der( ++ enveloped, another_cert, another_private_key, [] ++ ) + + def test_smime_decrypt_unsupported_key_encryption_algorithm( + self, backend, data, certificate, private_key +@@ -1373,7 +1385,7 @@ class TestPKCS7Decrypt: + mode="rb", + ) + +- with pytest.raises(exceptions.UnsupportedAlgorithm): ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): + pkcs7.pkcs7_decrypt_pem(enveloped, certificate, private_key, []) + + def test_smime_decrypt_not_enveloped( +diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py +index 17c8c7c..7af9899 100644 +--- a/tests/hazmat/primitives/test_rsa.py ++++ b/tests/hazmat/primitives/test_rsa.py +@@ -1710,8 +1710,9 @@ class TestRSADecryption: + ).private_key(backend, unsafe_skip_rsa_key_validation=True) + ciphertext = binascii.unhexlify(example["encryption"]) + assert len(ciphertext) == (skey.key_size + 7) // 8 +- message = skey.decrypt(ciphertext, padding.PKCS1v15()) +- assert message == binascii.unhexlify(example["message"]) ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ message = skey.decrypt(ciphertext, padding.PKCS1v15()) ++ assert message == binascii.unhexlify(example["message"]) + + def test_unsupported_padding( + self, rsa_key_2048: rsa.RSAPrivateKey, backend +@@ -2069,11 +2070,12 @@ class TestRSAEncryption: + _check_fips_key_length(backend, private_key) + pt = b"encrypt me!" + public_key = private_key.public_key() +- ct = public_key.encrypt(pt, pad) +- assert ct != pt +- assert len(ct) == (public_key.key_size + 7) // 8 +- recovered_pt = private_key.decrypt(ct, pad) +- assert recovered_pt == pt ++ with pytest.raises(ValueError, match="RSA PKCS#1v1.5 has security problems and it has been banned."): ++ ct = public_key.encrypt(pt, pad) ++ assert ct != pt ++ assert len(ct) == (public_key.key_size + 7) // 8 ++ recovered_pt = private_key.decrypt(ct, pad) ++ assert recovered_pt == pt + + @pytest.mark.parametrize( + ("key_data", "pad"), +-- +2.27.0 + diff --git a/python-cryptography.spec b/python-cryptography.spec index 9e7250539892394c6e33f57d50495ab0887e44c9..0605d9a9ec7c8e6593870e96a5e66c55a6e4750d 100644 --- a/python-cryptography.spec +++ b/python-cryptography.spec @@ -1,7 +1,7 @@ %global pypi_name cryptography Name: python-%{pypi_name} Version: 45.0.5 -Release: 1 +Release: 2 Summary: PyCA's cryptography library License: (Apache-2.0 OR BSD-3-Clause) AND PSF-2.0 URL: https://cryptography.io/en/latest/ @@ -13,6 +13,8 @@ Source0: %{pypi_source %{pypi_name}} # Note: Cargo needs to be consistent with the cargo version in the compile environment. Source1: cargo-vendor-cache +Patch9000: disable-RSA-PKCS-1v1.5-padding-to-fix-CVE-2023-50782.patch + BuildRequires: openssl-devel cargo BuildRequires: gcc BuildRequires: rust-packaging rust @@ -92,6 +94,9 @@ PYTHONPATH=%{buildroot}%{python3_sitearch} %{__python3} -m pytest --ignore vendo %doc README.rst docs %changelog +* Thu Jul 24 2025 shixuantong - 45.0.5-2 +- disable RSA PKCS#1v1.5 padding to fix CVE-2023-50782 + * Wed Jul 16 2025 Dongxing Wang - 45.0.5-1 - Upgrade package to 45.0.5