diff --git a/CHANGELOG.rst b/CHANGELOG.rst index df5c4bad3553..a4aa8b380ae5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -18,6 +18,8 @@ Changelog * Support for 32-bit Windows (including publishing wheels) is deprecated and will be removed in the next release. Users should move to a 64-bit Python installation. +* ``public_bytes`` methods on public keys now raise ``TypeError`` (instead of + ``ValueError`` if an invalid encoding is provided for the given ``format``). .. _v46-0-2: diff --git a/src/rust/src/backend/utils.rs b/src/rust/src/backend/utils.rs index d61466da4870..58d00b85ba1f 100644 --- a/src/rust/src/backend/utils.rs +++ b/src/rust/src/backend/utils.rs @@ -288,18 +288,9 @@ pub(crate) fn pkey_public_bytes<'p>( // SubjectPublicKeyInfo + PEM/DER if format.is(&types::PUBLIC_FORMAT_SUBJECT_PUBLIC_KEY_INFO.get(py)?) { - if encoding.is(&types::ENCODING_PEM.get(py)?) { - let pem_bytes = pkey.public_key_to_pem()?; - return Ok(pyo3::types::PyBytes::new(py, &pem_bytes)); - } else if encoding.is(&types::ENCODING_DER.get(py)?) { - let der_bytes = pkey.public_key_to_der()?; - return Ok(pyo3::types::PyBytes::new(py, &der_bytes)); - } - return Err(CryptographyError::from( - pyo3::exceptions::PyValueError::new_err( - "SubjectPublicKeyInfo works only with PEM or DER encoding", - ), - )); + let der_bytes = pkey.public_key_to_der()?; + + return crate::asn1::encode_der_data(py, "PUBLIC KEY".to_string(), der_bytes, encoding); } if let Ok(ec) = pkey.ec_key() { @@ -325,18 +316,14 @@ pub(crate) fn pkey_public_bytes<'p>( if let Ok(rsa) = pkey.rsa() { if format.is(&types::PUBLIC_FORMAT_PKCS1.get(py)?) { - if encoding.is(&types::ENCODING_PEM.get(py)?) { - let pem_bytes = rsa.public_key_to_pem_pkcs1()?; - return Ok(pyo3::types::PyBytes::new(py, &pem_bytes)); - } else if encoding.is(&types::ENCODING_DER.get(py)?) { - let der_bytes = rsa.public_key_to_der_pkcs1()?; - return Ok(pyo3::types::PyBytes::new(py, &der_bytes)); - } - return Err(CryptographyError::from( - pyo3::exceptions::PyValueError::new_err( - "PKCS1 works only with PEM or DER encoding", - ), - )); + let der_bytes = rsa.public_key_to_der_pkcs1()?; + + return crate::asn1::encode_der_data( + py, + "RSA PUBLIC KEY".to_string(), + der_bytes, + encoding, + ); } } diff --git a/tests/hazmat/primitives/test_dh.py b/tests/hazmat/primitives/test_dh.py index befe16bf97aa..987c69c5ea76 100644 --- a/tests/hazmat/primitives/test_dh.py +++ b/tests/hazmat/primitives/test_dh.py @@ -953,7 +953,7 @@ def test_public_bytes_values( def test_public_bytes_rejects_invalid(self, encoding, fmt, backend): parameters = FFDH3072_P.parameters(backend) key = parameters.generate_private_key().public_key() - with pytest.raises(ValueError): + with pytest.raises((ValueError, TypeError)): key.public_bytes(encoding, fmt) def test_parameter_bytes_invalid_encoding(self, backend): diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py index 3979de79cd72..389f4e3f765d 100644 --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -1057,5 +1057,5 @@ def test_public_bytes_pkcs1_unsupported(self, backend): ) def test_public_bytes_rejects_invalid(self, encoding, fmt, backend): key = DSA_KEY_2048.private_key(backend).public_key() - with pytest.raises(ValueError): + with pytest.raises((ValueError, TypeError)): key.public_bytes(encoding, fmt) diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index 2f62e46db5fb..38a505ca3a2b 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -1274,7 +1274,7 @@ def test_public_bytes_invalid_encoding(self, backend): def test_public_bytes_rejects_invalid(self, encoding, fmt, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) key = ec.generate_private_key(ec.SECP256R1(), backend).public_key() - with pytest.raises(ValueError): + with pytest.raises((TypeError, ValueError)): key.public_bytes(encoding, fmt) def test_public_bytes_invalid_format(self, backend): diff --git a/tests/hazmat/primitives/test_rsa.py b/tests/hazmat/primitives/test_rsa.py index 25edfb07592c..2e53796c158b 100644 --- a/tests/hazmat/primitives/test_rsa.py +++ b/tests/hazmat/primitives/test_rsa.py @@ -2709,12 +2709,12 @@ def test_public_bytes_openssh(self, backend): key.public_bytes( serialization.Encoding.DER, serialization.PublicFormat.OpenSSH ) - with pytest.raises(ValueError): + with pytest.raises(TypeError): key.public_bytes( serialization.Encoding.OpenSSH, serialization.PublicFormat.PKCS1, ) - with pytest.raises(ValueError): + with pytest.raises(TypeError): key.public_bytes( serialization.Encoding.OpenSSH, serialization.PublicFormat.SubjectPublicKeyInfo, @@ -2767,7 +2767,7 @@ def test_public_bytes_rejects_invalid( self, rsa_key_2048: rsa.RSAPrivateKey, encoding, fmt, backend ): key = rsa_key_2048.public_key() - with pytest.raises(ValueError): + with pytest.raises((ValueError, TypeError)): key.public_bytes(encoding, fmt) def test_public_key_equality(self, rsa_key_2048: rsa.RSAPrivateKey): diff --git a/tests/hazmat/primitives/test_serialization.py b/tests/hazmat/primitives/test_serialization.py index 3e15bccc7281..1cc51e55a3c3 100644 --- a/tests/hazmat/primitives/test_serialization.py +++ b/tests/hazmat/primitives/test_serialization.py @@ -1785,7 +1785,7 @@ def test_dh_public_key(self, backend): ): # tested elsewhere continue - with pytest.raises(ValueError): + with pytest.raises((TypeError, ValueError)): public_key.public_bytes(enc, fmt) @pytest.mark.skip_fips(reason="non-FIPS parameters") diff --git a/tests/hazmat/primitives/test_x25519.py b/tests/hazmat/primitives/test_x25519.py index 6597c2ae9c32..23a4b60b15e0 100644 --- a/tests/hazmat/primitives/test_x25519.py +++ b/tests/hazmat/primitives/test_x25519.py @@ -111,7 +111,7 @@ def test_public_bytes_bad_args(self, backend): serialization.Encoding.DER, None, # type: ignore[arg-type] ) - with pytest.raises(ValueError): + with pytest.raises(TypeError): key.public_bytes( serialization.Encoding.SMIME, serialization.PublicFormat.SubjectPublicKeyInfo,