Skip to content

Commit

Permalink
support bytes-like consistently across our asym sign/verify APIs (#10260
Browse files Browse the repository at this point in the history
) (#10265)

and update our docs to show it as well
  • Loading branch information
reaperhulk committed Jan 26, 2024
1 parent 6478f7e commit 92fa9f2
Show file tree
Hide file tree
Showing 12 changed files with 75 additions and 32 deletions.
9 changes: 6 additions & 3 deletions docs/hazmat/primitives/asymmetric/dsa.rst
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
9 changes: 6 additions & 3 deletions docs/hazmat/primitives/asymmetric/ec.rst
Expand Up @@ -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`.
Expand Down Expand Up @@ -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`.
Expand Down
9 changes: 6 additions & 3 deletions docs/hazmat/primitives/asymmetric/ed25519.rst
Expand Up @@ -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.

Expand Down Expand Up @@ -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
Expand Down
9 changes: 6 additions & 3 deletions docs/hazmat/primitives/asymmetric/ed448.rst
Expand Up @@ -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.

Expand Down Expand Up @@ -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
Expand Down
13 changes: 7 additions & 6 deletions src/rust/src/backend/dsa.rs
Expand Up @@ -3,6 +3,7 @@
// for complete details.

use crate::backend::utils;
use crate::buf::CffiBuf;
use crate::error::{CryptographyError, CryptographyResult};
use crate::exceptions;

Expand Down Expand Up @@ -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()?;
Expand Down Expand Up @@ -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(()),
Expand Down
13 changes: 7 additions & 6 deletions src/rust/src/backend/ec.rs
Expand Up @@ -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};

Expand Down Expand Up @@ -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)?)? {
Expand All @@ -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"))?,
)?;

Expand Down Expand Up @@ -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)?)? {
Expand All @@ -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(()),
Expand Down
8 changes: 4 additions & 4 deletions src/rust/src/backend/ed25519.rs
Expand Up @@ -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(())
Expand Down Expand Up @@ -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 {
Expand Down
8 changes: 4 additions & 4 deletions src/rust/src/backend/ed448.rs
Expand Up @@ -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(())
Expand Down Expand Up @@ -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(
Expand Down
8 changes: 8 additions & 0 deletions tests/hazmat/primitives/test_dsa.py
Expand Up @@ -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"
Expand Down
9 changes: 9 additions & 0 deletions tests/hazmat/primitives/test_ec.py
Expand Up @@ -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"
Expand Down
6 changes: 6 additions & 0 deletions tests/hazmat/primitives/test_ed25519.py
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions tests/hazmat/primitives/test_ed448.py
Expand Up @@ -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
Expand Down

0 comments on commit 92fa9f2

Please sign in to comment.