Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ Changelog
* Removed the deprecated ``CAST5``, ``SEED``, ``IDEA``, and ``Blowfish``
classes from the cipher module. These are still available in
:doc:`/hazmat/decrepit/index`.
* Make instances of
:class:`~cryptography.hazmat.primitives.hashes.HashAlgorithm` as well as
instances of classes in
:mod:`~cryptography.hazmat.primitives.asymmetric.padding`
comparable.

.. _v45-0-6:

Expand Down
2 changes: 1 addition & 1 deletion docs/hazmat/primitives/asymmetric/cloudhsm.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ if you only need a subset of functionality.
... Maps the cryptography padding and algorithm to the corresponding KMS signing algorithm.
... This is specific to your implementation.
... """
... if isinstance(padding, PKCS1v15) and isinstance(algorithm, hashes.SHA256):
... if padding == PKCS1v15() and algorithm == hashes.SHA256():
... return b"RSA_PKCS1_V1_5_SHA_256"
... else:
... raise NotImplementedError()
Expand Down
10 changes: 5 additions & 5 deletions docs/x509/reference.rst
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ Loading Certificate Revocation Lists
>>> from cryptography import x509
>>> from cryptography.hazmat.primitives import hashes
>>> crl = x509.load_pem_x509_crl(pem_crl_data)
>>> isinstance(crl.signature_hash_algorithm, hashes.SHA256)
>>> crl.signature_hash_algorithm == hashes.SHA256()
True

.. function:: load_der_x509_crl(data)
Expand Down Expand Up @@ -287,7 +287,7 @@ Loading Certificate Signing Requests
>>> from cryptography import x509
>>> from cryptography.hazmat.primitives import hashes
>>> csr = x509.load_pem_x509_csr(pem_req_data)
>>> isinstance(csr.signature_hash_algorithm, hashes.SHA256)
>>> csr.signature_hash_algorithm == hashes.SHA256()
True

.. function:: load_der_x509_csr(data)
Expand Down Expand Up @@ -477,7 +477,7 @@ X.509 Certificate Object
.. doctest::

>>> from cryptography.hazmat.primitives import hashes
>>> isinstance(cert.signature_hash_algorithm, hashes.SHA256)
>>> cert.signature_hash_algorithm == hashes.SHA256()
True

.. attribute:: signature_algorithm_oid
Expand Down Expand Up @@ -716,7 +716,7 @@ X.509 CRL (Certificate Revocation List) Object
.. doctest::

>>> from cryptography.hazmat.primitives import hashes
>>> isinstance(crl.signature_hash_algorithm, hashes.SHA256)
>>> crl.signature_hash_algorithm == hashes.SHA256()
True

.. attribute:: signature_algorithm_oid
Expand Down Expand Up @@ -1119,7 +1119,7 @@ X.509 CSR (Certificate Signing Request) Object
.. doctest::

>>> from cryptography.hazmat.primitives import hashes
>>> isinstance(csr.signature_hash_algorithm, hashes.SHA256)
>>> csr.signature_hash_algorithm == hashes.SHA256()
True

.. attribute:: signature_algorithm_oid
Expand Down
34 changes: 34 additions & 0 deletions src/cryptography/hazmat/primitives/asymmetric/padding.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from __future__ import annotations

import abc
import typing

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives._asymmetric import (
Expand All @@ -16,6 +17,9 @@
class PKCS1v15(AsymmetricPadding):
name = "EMSA-PKCS1-v1_5"

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, PKCS1v15)


class _MaxLength:
"Sentinel value for `MAX_LENGTH`."
Expand Down Expand Up @@ -56,6 +60,18 @@ def __init__(

self._salt_length = salt_length

def __eq__(self, other: typing.Any) -> bool:
if isinstance(self._salt_length, int):
eq_salt_length = self._salt_length == other._salt_length
else:
eq_salt_length = self._salt_length is other._salt_length

return (
isinstance(other, PSS)
and eq_salt_length
and self._mgf == other._mgf
)

@property
def mgf(self) -> MGF:
return self._mgf
Expand All @@ -77,6 +93,14 @@ def __init__(
self._algorithm = algorithm
self._label = label

def __eq__(self, other: typing.Any) -> bool:
return (
isinstance(other, OAEP)
and self._mgf == other._mgf
and self._algorithm == other._algorithm
and self._label == other._label
)

@property
def algorithm(self) -> hashes.HashAlgorithm:
return self._algorithm
Expand All @@ -89,6 +113,13 @@ def mgf(self) -> MGF:
class MGF(metaclass=abc.ABCMeta):
_algorithm: hashes.HashAlgorithm

@abc.abstractmethod
def __eq__(self, other: typing.Any) -> bool:
"""
Implement equality checking.
"""
...


class MGF1(MGF):
def __init__(self, algorithm: hashes.HashAlgorithm):
Expand All @@ -97,6 +128,9 @@ def __init__(self, algorithm: hashes.HashAlgorithm):

self._algorithm = algorithm

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, MGF1) and self._algorithm == other._algorithm


def calculate_max_pss_salt_length(
key: rsa.RSAPrivateKey | rsa.RSAPublicKey,
Expand Down
71 changes: 71 additions & 0 deletions src/cryptography/hazmat/primitives/hashes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from __future__ import annotations

import abc
import typing

from cryptography.hazmat.bindings._rust import openssl as rust_openssl
from cryptography.utils import Buffer
Expand Down Expand Up @@ -36,6 +37,13 @@


class HashAlgorithm(metaclass=abc.ABCMeta):
@abc.abstractmethod
def __eq__(self, other: typing.Any) -> bool:
"""
Implement equality checking.
"""
...

@property
@abc.abstractmethod
def name(self) -> str:
Expand Down Expand Up @@ -103,66 +111,99 @@ class SHA1(HashAlgorithm):
digest_size = 20
block_size = 64

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, SHA1)


class SHA512_224(HashAlgorithm): # noqa: N801
name = "sha512-224"
digest_size = 28
block_size = 128

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, SHA512_224)


class SHA512_256(HashAlgorithm): # noqa: N801
name = "sha512-256"
digest_size = 32
block_size = 128

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, SHA512_256)


class SHA224(HashAlgorithm):
name = "sha224"
digest_size = 28
block_size = 64

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, SHA224)


class SHA256(HashAlgorithm):
name = "sha256"
digest_size = 32
block_size = 64

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, SHA256)


class SHA384(HashAlgorithm):
name = "sha384"
digest_size = 48
block_size = 128

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, SHA384)


class SHA512(HashAlgorithm):
name = "sha512"
digest_size = 64
block_size = 128

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, SHA512)


class SHA3_224(HashAlgorithm): # noqa: N801
name = "sha3-224"
digest_size = 28
block_size = None

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, SHA3_224)


class SHA3_256(HashAlgorithm): # noqa: N801
name = "sha3-256"
digest_size = 32
block_size = None

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, SHA3_256)


class SHA3_384(HashAlgorithm): # noqa: N801
name = "sha3-384"
digest_size = 48
block_size = None

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, SHA3_384)


class SHA3_512(HashAlgorithm): # noqa: N801
name = "sha3-512"
digest_size = 64
block_size = None

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, SHA3_512)


class SHAKE128(HashAlgorithm, ExtendableOutputFunction):
name = "shake128"
Expand All @@ -177,6 +218,12 @@ def __init__(self, digest_size: int):

self._digest_size = digest_size

def __eq__(self, other: typing.Any) -> bool:
return (
isinstance(other, SHAKE128)
and self._digest_size == other._digest_size
)

@property
def digest_size(self) -> int:
return self._digest_size
Expand All @@ -195,6 +242,12 @@ def __init__(self, digest_size: int):

self._digest_size = digest_size

def __eq__(self, other: typing.Any) -> bool:
return (
isinstance(other, SHAKE256)
and self._digest_size == other._digest_size
)

@property
def digest_size(self) -> int:
return self._digest_size
Expand All @@ -205,6 +258,9 @@ class MD5(HashAlgorithm):
digest_size = 16
block_size = 64

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, MD5)


class BLAKE2b(HashAlgorithm):
name = "blake2b"
Expand All @@ -218,6 +274,12 @@ def __init__(self, digest_size: int):

self._digest_size = digest_size

def __eq__(self, other: typing.Any) -> bool:
return (
isinstance(other, BLAKE2b)
and self._digest_size == other._digest_size
)

@property
def digest_size(self) -> int:
return self._digest_size
Expand All @@ -235,6 +297,12 @@ def __init__(self, digest_size: int):

self._digest_size = digest_size

def __eq__(self, other: typing.Any) -> bool:
return (
isinstance(other, BLAKE2s)
and self._digest_size == other._digest_size
)

@property
def digest_size(self) -> int:
return self._digest_size
Expand All @@ -244,3 +312,6 @@ class SM3(HashAlgorithm):
name = "sm3"
digest_size = 32
block_size = 64

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, SM3)
7 changes: 7 additions & 0 deletions tests/doubles.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# 2.0, and the BSD License. See the LICENSE file in the root of this repository
# for complete details.

import typing

from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding
Expand Down Expand Up @@ -40,6 +41,12 @@ class DummyHashAlgorithm(hashes.HashAlgorithm):
def __init__(self, digest_size: int = 32) -> None:
self._digest_size = digest_size

def __eq__(self, other: typing.Any) -> bool:
return (
isinstance(self, DummyHashAlgorithm)
and self._digest_size == other._digest_size
)

@property
def digest_size(self) -> int:
return self._digest_size
Expand Down
4 changes: 4 additions & 0 deletions tests/hazmat/backends/test_openssl.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@


import itertools
import typing

import pytest

Expand Down Expand Up @@ -32,6 +33,9 @@ class DummyMGF(padding.MGF):
_salt_length = 0
_algorithm = hashes.SHA1()

def __eq__(self, other: typing.Any) -> bool:
return isinstance(other, DummyMGF)


class TestOpenSSL:
def test_backend_exists(self):
Expand Down
Loading
Loading