123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- # This file is dual licensed under the terms of the Apache License, Version
- # 2.0, and the BSD License. See the LICENSE file in the root of this repository
- # for complete details.
- import abc
- import typing
- from cryptography import utils
- from cryptography.exceptions import (
- AlreadyFinalized,
- UnsupportedAlgorithm,
- _Reasons,
- )
- from cryptography.hazmat.backends import _get_backend
- from cryptography.hazmat.backends.interfaces import Backend, HashBackend
- class HashAlgorithm(metaclass=abc.ABCMeta):
- @abc.abstractproperty
- def name(self) -> str:
- """
- A string naming this algorithm (e.g. "sha256", "md5").
- """
- @abc.abstractproperty
- def digest_size(self) -> int:
- """
- The size of the resulting digest in bytes.
- """
- @abc.abstractproperty
- def block_size(self) -> typing.Optional[int]:
- """
- The internal block size of the hash function, or None if the hash
- function does not use blocks internally (e.g. SHA3).
- """
- class HashContext(metaclass=abc.ABCMeta):
- @abc.abstractproperty
- def algorithm(self) -> HashAlgorithm:
- """
- A HashAlgorithm that will be used by this context.
- """
- @abc.abstractmethod
- def update(self, data: bytes) -> None:
- """
- Processes the provided bytes through the hash.
- """
- @abc.abstractmethod
- def finalize(self) -> bytes:
- """
- Finalizes the hash context and returns the hash digest as bytes.
- """
- @abc.abstractmethod
- def copy(self) -> "HashContext":
- """
- Return a HashContext that is a copy of the current context.
- """
- class ExtendableOutputFunction(metaclass=abc.ABCMeta):
- """
- An interface for extendable output functions.
- """
- class Hash(HashContext):
- def __init__(
- self,
- algorithm: HashAlgorithm,
- backend: typing.Optional[Backend] = None,
- ctx: typing.Optional["HashContext"] = None,
- ):
- backend = _get_backend(backend)
- if not isinstance(backend, HashBackend):
- raise UnsupportedAlgorithm(
- "Backend object does not implement HashBackend.",
- _Reasons.BACKEND_MISSING_INTERFACE,
- )
- if not isinstance(algorithm, HashAlgorithm):
- raise TypeError("Expected instance of hashes.HashAlgorithm.")
- self._algorithm = algorithm
- self._backend = backend
- if ctx is None:
- self._ctx = self._backend.create_hash_ctx(self.algorithm)
- else:
- self._ctx = ctx
- @property
- def algorithm(self) -> HashAlgorithm:
- return self._algorithm
- def update(self, data: bytes) -> None:
- if self._ctx is None:
- raise AlreadyFinalized("Context was already finalized.")
- utils._check_byteslike("data", data)
- self._ctx.update(data)
- def copy(self) -> "Hash":
- if self._ctx is None:
- raise AlreadyFinalized("Context was already finalized.")
- return Hash(
- self.algorithm, backend=self._backend, ctx=self._ctx.copy()
- )
- def finalize(self) -> bytes:
- if self._ctx is None:
- raise AlreadyFinalized("Context was already finalized.")
- digest = self._ctx.finalize()
- self._ctx = None
- return digest
- class SHA1(HashAlgorithm):
- name = "sha1"
- digest_size = 20
- block_size = 64
- class SHA512_224(HashAlgorithm): # noqa: N801
- name = "sha512-224"
- digest_size = 28
- block_size = 128
- class SHA512_256(HashAlgorithm): # noqa: N801
- name = "sha512-256"
- digest_size = 32
- block_size = 128
- class SHA224(HashAlgorithm):
- name = "sha224"
- digest_size = 28
- block_size = 64
- class SHA256(HashAlgorithm):
- name = "sha256"
- digest_size = 32
- block_size = 64
- class SHA384(HashAlgorithm):
- name = "sha384"
- digest_size = 48
- block_size = 128
- class SHA512(HashAlgorithm):
- name = "sha512"
- digest_size = 64
- block_size = 128
- class SHA3_224(HashAlgorithm): # noqa: N801
- name = "sha3-224"
- digest_size = 28
- block_size = None
- class SHA3_256(HashAlgorithm): # noqa: N801
- name = "sha3-256"
- digest_size = 32
- block_size = None
- class SHA3_384(HashAlgorithm): # noqa: N801
- name = "sha3-384"
- digest_size = 48
- block_size = None
- class SHA3_512(HashAlgorithm): # noqa: N801
- name = "sha3-512"
- digest_size = 64
- block_size = None
- class SHAKE128(HashAlgorithm, ExtendableOutputFunction):
- name = "shake128"
- block_size = None
- def __init__(self, digest_size: int):
- if not isinstance(digest_size, int):
- raise TypeError("digest_size must be an integer")
- if digest_size < 1:
- raise ValueError("digest_size must be a positive integer")
- self._digest_size = digest_size
- @property
- def digest_size(self) -> int:
- return self._digest_size
- class SHAKE256(HashAlgorithm, ExtendableOutputFunction):
- name = "shake256"
- block_size = None
- def __init__(self, digest_size: int):
- if not isinstance(digest_size, int):
- raise TypeError("digest_size must be an integer")
- if digest_size < 1:
- raise ValueError("digest_size must be a positive integer")
- self._digest_size = digest_size
- @property
- def digest_size(self) -> int:
- return self._digest_size
- class MD5(HashAlgorithm):
- name = "md5"
- digest_size = 16
- block_size = 64
- class BLAKE2b(HashAlgorithm):
- name = "blake2b"
- _max_digest_size = 64
- _min_digest_size = 1
- block_size = 128
- def __init__(self, digest_size: int):
- if digest_size != 64:
- raise ValueError("Digest size must be 64")
- self._digest_size = digest_size
- @property
- def digest_size(self) -> int:
- return self._digest_size
- class BLAKE2s(HashAlgorithm):
- name = "blake2s"
- block_size = 64
- _max_digest_size = 32
- _min_digest_size = 1
- def __init__(self, digest_size: int):
- if digest_size != 32:
- raise ValueError("Digest size must be 32")
- self._digest_size = digest_size
- @property
- def digest_size(self) -> int:
- return self._digest_size
- class SM3(HashAlgorithm):
- name = "sm3"
- digest_size = 32
- block_size = 64
|