From 92fa9f2f606caea5d499c825e832be5bac6f0c23 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Fri, 26 Jan 2024 08:48:45 -0800 Subject: [PATCH] support bytes-like consistently across our asym sign/verify APIs (#10260) (#10265) and update our docs to show it as well --- docs/hazmat/primitives/asymmetric/dsa.rst | 9 ++++++--- docs/hazmat/primitives/asymmetric/ec.rst | 9 ++++++--- docs/hazmat/primitives/asymmetric/ed25519.rst | 9 ++++++--- docs/hazmat/primitives/asymmetric/ed448.rst | 9 ++++++--- src/rust/src/backend/dsa.rs | 13 +++++++------ src/rust/src/backend/ec.rs | 13 +++++++------ src/rust/src/backend/ed25519.rs | 8 ++++---- src/rust/src/backend/ed448.rs | 8 ++++---- tests/hazmat/primitives/test_dsa.py | 8 ++++++++ tests/hazmat/primitives/test_ec.py | 9 +++++++++ tests/hazmat/primitives/test_ed25519.py | 6 ++++++ tests/hazmat/primitives/test_ed448.py | 6 ++++++ 12 files changed, 75 insertions(+), 32 deletions(-) diff --git a/docs/hazmat/primitives/asymmetric/dsa.rst b/docs/hazmat/primitives/asymmetric/dsa.rst index bcd4c993d20a..b159a09116ff 100644 --- a/docs/hazmat/primitives/asymmetric/dsa.rst +++ b/docs/hazmat/primitives/asymmetric/dsa.rst @@ -289,7 +289,8 @@ Key interfaces Sign one block of data which can be verified later by others using the public key. - :param bytes data: The message string to sign. + :param data: The message string to sign. + :type data: :term:`bytes-like` :param algorithm: An instance of :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or @@ -391,9 +392,11 @@ Key interfaces Verify one block of data was signed by the private key associated with this public key. - :param bytes signature: The signature to verify. + :param signature: The signature to verify. + :type signature: :term:`bytes-like` - :param bytes data: The message string that was signed. + :param data: The message string that was signed. + :type data: :term:`bytes-like` :param algorithm: An instance of :class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` or diff --git a/docs/hazmat/primitives/asymmetric/ec.rst b/docs/hazmat/primitives/asymmetric/ec.rst index 561218c35c72..75165b6a4536 100644 --- a/docs/hazmat/primitives/asymmetric/ec.rst +++ b/docs/hazmat/primitives/asymmetric/ec.rst @@ -569,7 +569,8 @@ Key Interfaces Sign one block of data which can be verified later by others using the public key. - :param bytes data: The message string to sign. + :param data: The message string to sign. + :type data: :term:`bytes-like` :param signature_algorithm: An instance of :class:`EllipticCurveSignatureAlgorithm`, such as :class:`ECDSA`. @@ -678,12 +679,14 @@ Key Interfaces Verify one block of data was signed by the private key associated with this public key. - :param bytes signature: The DER-encoded signature to verify. + :param signature: The DER-encoded signature to verify. A raw signature may be DER-encoded by splitting it into the ``r`` and ``s`` components and passing them into :func:`~cryptography.hazmat.primitives.asymmetric.utils.encode_dss_signature`. + :type signature: :term:`bytes-like` - :param bytes data: The message string that was signed. + :param data: The message string that was signed. + :type data: :term:`bytes-like` :param signature_algorithm: An instance of :class:`EllipticCurveSignatureAlgorithm`. diff --git a/docs/hazmat/primitives/asymmetric/ed25519.rst b/docs/hazmat/primitives/asymmetric/ed25519.rst index 1ca06fc1b9f2..8d4b910ca115 100644 --- a/docs/hazmat/primitives/asymmetric/ed25519.rst +++ b/docs/hazmat/primitives/asymmetric/ed25519.rst @@ -67,7 +67,8 @@ Key interfaces .. method:: sign(data) - :param bytes data: The data to sign. + :param data: The data to sign. + :type data: :term:`bytes-like` :returns bytes: The 64 byte signature. @@ -192,9 +193,11 @@ Key interfaces .. method:: verify(signature, data) - :param bytes signature: The signature to verify. + :param signature: The signature to verify. + :type signature: :term:`bytes-like` - :param bytes data: The data to verify. + :param data: The data to verify. + :type data: :term:`bytes-like` :returns: None :raises cryptography.exceptions.InvalidSignature: Raised when the diff --git a/docs/hazmat/primitives/asymmetric/ed448.rst b/docs/hazmat/primitives/asymmetric/ed448.rst index efe245d568e9..27a8092db59c 100644 --- a/docs/hazmat/primitives/asymmetric/ed448.rst +++ b/docs/hazmat/primitives/asymmetric/ed448.rst @@ -47,7 +47,8 @@ Key interfaces .. method:: sign(data) - :param bytes data: The data to sign. + :param data: The data to sign. + :type data: :term:`bytes-like` :returns bytes: The 114 byte signature. @@ -146,9 +147,11 @@ Key interfaces .. method:: verify(signature, data) - :param bytes signature: The signature to verify. + :param signature: The signature to verify. + :type signature: :term:`bytes-like` - :param bytes data: The data to verify. + :param data: The data to verify. + :type data: :term:`bytes-like` :returns: None :raises cryptography.exceptions.InvalidSignature: Raised when the diff --git a/src/rust/src/backend/dsa.rs b/src/rust/src/backend/dsa.rs index cf0824613fdb..bf341ac71314 100644 --- a/src/rust/src/backend/dsa.rs +++ b/src/rust/src/backend/dsa.rs @@ -3,6 +3,7 @@ // for complete details. use crate::backend::utils; +use crate::buf::CffiBuf; use crate::error::{CryptographyError, CryptographyResult}; use crate::exceptions; @@ -66,10 +67,10 @@ impl DsaPrivateKey { fn sign<'p>( &self, py: pyo3::Python<'p>, - data: &[u8], + data: CffiBuf<'_>, algorithm: &pyo3::PyAny, ) -> CryptographyResult<&'p pyo3::types::PyBytes> { - let (data, _) = utils::calculate_digest_and_algorithm(py, data, algorithm)?; + let (data, _) = utils::calculate_digest_and_algorithm(py, data.as_bytes(), algorithm)?; let mut signer = openssl::pkey_ctx::PkeyCtx::new(&self.pkey)?; signer.sign_init()?; @@ -151,15 +152,15 @@ impl DsaPublicKey { fn verify( &self, py: pyo3::Python<'_>, - signature: &[u8], - data: &[u8], + signature: CffiBuf<'_>, + data: CffiBuf<'_>, algorithm: &pyo3::PyAny, ) -> CryptographyResult<()> { - let (data, _) = utils::calculate_digest_and_algorithm(py, data, algorithm)?; + let (data, _) = utils::calculate_digest_and_algorithm(py, data.as_bytes(), algorithm)?; let mut verifier = openssl::pkey_ctx::PkeyCtx::new(&self.pkey)?; verifier.verify_init()?; - let valid = verifier.verify(data, signature).unwrap_or(false); + let valid = verifier.verify(data, signature.as_bytes()).unwrap_or(false); if !valid { return Err(CryptographyError::from( exceptions::InvalidSignature::new_err(()), diff --git a/src/rust/src/backend/ec.rs b/src/rust/src/backend/ec.rs index 459da6103d3b..5a01412981d2 100644 --- a/src/rust/src/backend/ec.rs +++ b/src/rust/src/backend/ec.rs @@ -8,6 +8,7 @@ use std::hash::{Hash, Hasher}; use pyo3::ToPyObject; use crate::backend::utils; +use crate::buf::CffiBuf; use crate::error::{CryptographyError, CryptographyResult}; use crate::{exceptions, types}; @@ -268,7 +269,7 @@ impl ECPrivateKey { fn sign<'p>( &self, py: pyo3::Python<'p>, - data: &[u8], + data: CffiBuf<'_>, signature_algorithm: &pyo3::PyAny, ) -> CryptographyResult<&'p pyo3::types::PyBytes> { if !signature_algorithm.is_instance(types::ECDSA.get(py)?)? { @@ -282,7 +283,7 @@ impl ECPrivateKey { let (data, _) = utils::calculate_digest_and_algorithm( py, - data, + data.as_bytes(), signature_algorithm.getattr(pyo3::intern!(py, "algorithm"))?, )?; @@ -366,8 +367,8 @@ impl ECPublicKey { fn verify( &self, py: pyo3::Python<'_>, - signature: &[u8], - data: &[u8], + signature: CffiBuf<'_>, + data: CffiBuf<'_>, signature_algorithm: &pyo3::PyAny, ) -> CryptographyResult<()> { if !signature_algorithm.is_instance(types::ECDSA.get(py)?)? { @@ -381,13 +382,13 @@ impl ECPublicKey { let (data, _) = utils::calculate_digest_and_algorithm( py, - data, + data.as_bytes(), signature_algorithm.getattr(pyo3::intern!(py, "algorithm"))?, )?; let mut verifier = openssl::pkey_ctx::PkeyCtx::new(&self.pkey)?; verifier.verify_init()?; - let valid = verifier.verify(data, signature).unwrap_or(false); + let valid = verifier.verify(data, signature.as_bytes()).unwrap_or(false); if !valid { return Err(CryptographyError::from( exceptions::InvalidSignature::new_err(()), diff --git a/src/rust/src/backend/ed25519.rs b/src/rust/src/backend/ed25519.rs index f68da83bfb47..81ca3230088e 100644 --- a/src/rust/src/backend/ed25519.rs +++ b/src/rust/src/backend/ed25519.rs @@ -66,12 +66,12 @@ impl Ed25519PrivateKey { fn sign<'p>( &self, py: pyo3::Python<'p>, - data: &[u8], + data: CffiBuf<'_>, ) -> CryptographyResult<&'p pyo3::types::PyBytes> { let mut signer = openssl::sign::Signer::new_without_digest(&self.pkey)?; Ok(pyo3::types::PyBytes::new_with(py, signer.len()?, |b| { let n = signer - .sign_oneshot(b, data) + .sign_oneshot(b, data.as_bytes()) .map_err(CryptographyError::from)?; assert_eq!(n, b.len()); Ok(()) @@ -118,9 +118,9 @@ impl Ed25519PrivateKey { #[pyo3::prelude::pymethods] impl Ed25519PublicKey { - fn verify(&self, signature: &[u8], data: &[u8]) -> CryptographyResult<()> { + fn verify(&self, signature: CffiBuf<'_>, data: CffiBuf<'_>) -> CryptographyResult<()> { let valid = openssl::sign::Verifier::new_without_digest(&self.pkey)? - .verify_oneshot(signature, data) + .verify_oneshot(signature.as_bytes(), data.as_bytes()) .unwrap_or(false); if !valid { diff --git a/src/rust/src/backend/ed448.rs b/src/rust/src/backend/ed448.rs index eeed28e92f6e..15b679d5f993 100644 --- a/src/rust/src/backend/ed448.rs +++ b/src/rust/src/backend/ed448.rs @@ -64,12 +64,12 @@ impl Ed448PrivateKey { fn sign<'p>( &self, py: pyo3::Python<'p>, - data: &[u8], + data: CffiBuf<'_>, ) -> CryptographyResult<&'p pyo3::types::PyBytes> { let mut signer = openssl::sign::Signer::new_without_digest(&self.pkey)?; Ok(pyo3::types::PyBytes::new_with(py, signer.len()?, |b| { let n = signer - .sign_oneshot(b, data) + .sign_oneshot(b, data.as_bytes()) .map_err(CryptographyError::from)?; assert_eq!(n, b.len()); Ok(()) @@ -116,9 +116,9 @@ impl Ed448PrivateKey { #[pyo3::prelude::pymethods] impl Ed448PublicKey { - fn verify(&self, signature: &[u8], data: &[u8]) -> CryptographyResult<()> { + fn verify(&self, signature: CffiBuf<'_>, data: CffiBuf<'_>) -> CryptographyResult<()> { let valid = openssl::sign::Verifier::new_without_digest(&self.pkey)? - .verify_oneshot(signature, data)?; + .verify_oneshot(signature.as_bytes(), data.as_bytes())?; if !valid { return Err(CryptographyError::from( diff --git a/tests/hazmat/primitives/test_dsa.py b/tests/hazmat/primitives/test_dsa.py index c3990cd5af44..2928a1eb9d8c 100644 --- a/tests/hazmat/primitives/test_dsa.py +++ b/tests/hazmat/primitives/test_dsa.py @@ -522,6 +522,14 @@ def test_sign(self, backend): public_key = private_key.public_key() public_key.verify(signature, message, algorithm) + def test_sign_verify_buffer(self, backend): + private_key = DSA_KEY_1024.private_key(backend) + message = bytearray(b"one little message") + algorithm = hashes.SHA1() + signature = private_key.sign(message, algorithm) + public_key = private_key.public_key() + public_key.verify(bytearray(signature), message, algorithm) + def test_prehashed_sign(self, backend): private_key = DSA_KEY_1024.private_key(backend) message = b"one little message" diff --git a/tests/hazmat/primitives/test_ec.py b/tests/hazmat/primitives/test_ec.py index d794d429524e..334e76dcc073 100644 --- a/tests/hazmat/primitives/test_ec.py +++ b/tests/hazmat/primitives/test_ec.py @@ -516,6 +516,15 @@ def test_sign(self, backend): public_key = private_key.public_key() public_key.verify(signature, message, algorithm) + def test_sign_verify_buffers(self, backend): + _skip_curve_unsupported(backend, ec.SECP256R1()) + message = bytearray(b"one little message") + algorithm = ec.ECDSA(hashes.SHA1()) + private_key = ec.generate_private_key(ec.SECP256R1(), backend) + signature = private_key.sign(message, algorithm) + public_key = private_key.public_key() + public_key.verify(bytearray(signature), message, algorithm) + def test_sign_prehashed(self, backend): _skip_curve_unsupported(backend, ec.SECP256R1()) message = b"one little message" diff --git a/tests/hazmat/primitives/test_ed25519.py b/tests/hazmat/primitives/test_ed25519.py index 8e6b33b1fd62..26f7d0c71b07 100644 --- a/tests/hazmat/primitives/test_ed25519.py +++ b/tests/hazmat/primitives/test_ed25519.py @@ -117,6 +117,12 @@ def test_invalid_signature(self, backend): with pytest.raises(InvalidSignature): key.public_key().verify(b"0" * 64, b"test data") + def test_sign_verify_buffer(self, backend): + key = Ed25519PrivateKey.generate() + data = bytearray(b"test data") + signature = key.sign(data) + key.public_key().verify(bytearray(signature), data) + def test_generate(self, backend): key = Ed25519PrivateKey.generate() assert key diff --git a/tests/hazmat/primitives/test_ed448.py b/tests/hazmat/primitives/test_ed448.py index d363f38dfd96..6c7bdedea39d 100644 --- a/tests/hazmat/primitives/test_ed448.py +++ b/tests/hazmat/primitives/test_ed448.py @@ -86,6 +86,12 @@ def test_invalid_signature(self, backend): with pytest.raises(InvalidSignature): key.public_key().verify(b"0" * 64, b"test data") + def test_sign_verify_buffer(self, backend): + key = Ed448PrivateKey.generate() + data = bytearray(b"test data") + signature = key.sign(data) + key.public_key().verify(bytearray(signature), data) + def test_generate(self, backend): key = Ed448PrivateKey.generate() assert key