Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/cryptography/hazmat/primitives/hashes.py : 73%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1# This file is dual licensed under the terms of the Apache License, Version
2# 2.0, and the BSD License. See the LICENSE file in the root of this repository
3# for complete details.
5import abc
6import typing
8from cryptography import utils
9from cryptography.exceptions import (
10 AlreadyFinalized,
11 UnsupportedAlgorithm,
12 _Reasons,
13)
14from cryptography.hazmat.backends import _get_backend
15from cryptography.hazmat.backends.interfaces import HashBackend
18class HashAlgorithm(metaclass=abc.ABCMeta):
19 @abc.abstractproperty
20 def name(self) -> str:
21 """
22 A string naming this algorithm (e.g. "sha256", "md5").
23 """
25 @abc.abstractproperty
26 def digest_size(self) -> int:
27 """
28 The size of the resulting digest in bytes.
29 """
31 @abc.abstractproperty
32 def block_size(self) -> typing.Optional[int]:
33 """
34 The internal block size of the hash function, or None if the hash
35 function does not use blocks internally (e.g. SHA3).
36 """
39class HashContext(metaclass=abc.ABCMeta):
40 @abc.abstractproperty
41 def algorithm(self) -> HashAlgorithm:
42 """
43 A HashAlgorithm that will be used by this context.
44 """
46 @abc.abstractmethod
47 def update(self, data: bytes) -> None:
48 """
49 Processes the provided bytes through the hash.
50 """
52 @abc.abstractmethod
53 def finalize(self) -> bytes:
54 """
55 Finalizes the hash context and returns the hash digest as bytes.
56 """
58 @abc.abstractmethod
59 def copy(self) -> "HashContext":
60 """
61 Return a HashContext that is a copy of the current context.
62 """
65class ExtendableOutputFunction(metaclass=abc.ABCMeta):
66 """
67 An interface for extendable output functions.
68 """
71class Hash(HashContext):
72 def __init__(self, algorithm: HashAlgorithm, backend=None, ctx=None):
73 backend = _get_backend(backend)
74 if not isinstance(backend, HashBackend):
75 raise UnsupportedAlgorithm(
76 "Backend object does not implement HashBackend.",
77 _Reasons.BACKEND_MISSING_INTERFACE,
78 )
80 if not isinstance(algorithm, HashAlgorithm):
81 raise TypeError("Expected instance of hashes.HashAlgorithm.")
82 self._algorithm = algorithm
84 self._backend = backend
86 if ctx is None:
87 self._ctx = self._backend.create_hash_ctx(self.algorithm)
88 else:
89 self._ctx = ctx
91 algorithm = utils.read_only_property("_algorithm")
93 def update(self, data: bytes) -> None:
94 if self._ctx is None:
95 raise AlreadyFinalized("Context was already finalized.")
96 utils._check_byteslike("data", data)
97 self._ctx.update(data)
99 def copy(self) -> "Hash":
100 if self._ctx is None:
101 raise AlreadyFinalized("Context was already finalized.")
102 return Hash(
103 self.algorithm, backend=self._backend, ctx=self._ctx.copy()
104 )
106 def finalize(self) -> bytes:
107 if self._ctx is None:
108 raise AlreadyFinalized("Context was already finalized.")
109 digest = self._ctx.finalize()
110 self._ctx = None
111 return digest
114class SHA1(HashAlgorithm):
115 name = "sha1"
116 digest_size = 20
117 block_size = 64
120class SHA512_224(HashAlgorithm): # noqa: N801
121 name = "sha512-224"
122 digest_size = 28
123 block_size = 128
126class SHA512_256(HashAlgorithm): # noqa: N801
127 name = "sha512-256"
128 digest_size = 32
129 block_size = 128
132class SHA224(HashAlgorithm):
133 name = "sha224"
134 digest_size = 28
135 block_size = 64
138class SHA256(HashAlgorithm):
139 name = "sha256"
140 digest_size = 32
141 block_size = 64
144class SHA384(HashAlgorithm):
145 name = "sha384"
146 digest_size = 48
147 block_size = 128
150class SHA512(HashAlgorithm):
151 name = "sha512"
152 digest_size = 64
153 block_size = 128
156class SHA3_224(HashAlgorithm): # noqa: N801
157 name = "sha3-224"
158 digest_size = 28
159 block_size = None
162class SHA3_256(HashAlgorithm): # noqa: N801
163 name = "sha3-256"
164 digest_size = 32
165 block_size = None
168class SHA3_384(HashAlgorithm): # noqa: N801
169 name = "sha3-384"
170 digest_size = 48
171 block_size = None
174class SHA3_512(HashAlgorithm): # noqa: N801
175 name = "sha3-512"
176 digest_size = 64
177 block_size = None
180class SHAKE128(HashAlgorithm, ExtendableOutputFunction):
181 name = "shake128"
182 block_size = None
184 def __init__(self, digest_size: int):
185 if not isinstance(digest_size, int):
186 raise TypeError("digest_size must be an integer")
188 if digest_size < 1:
189 raise ValueError("digest_size must be a positive integer")
191 self._digest_size = digest_size
193 digest_size = utils.read_only_property("_digest_size")
196class SHAKE256(HashAlgorithm, ExtendableOutputFunction):
197 name = "shake256"
198 block_size = None
200 def __init__(self, digest_size: int):
201 if not isinstance(digest_size, int):
202 raise TypeError("digest_size must be an integer")
204 if digest_size < 1:
205 raise ValueError("digest_size must be a positive integer")
207 self._digest_size = digest_size
209 digest_size = utils.read_only_property("_digest_size")
212class MD5(HashAlgorithm):
213 name = "md5"
214 digest_size = 16
215 block_size = 64
218class BLAKE2b(HashAlgorithm):
219 name = "blake2b"
220 _max_digest_size = 64
221 _min_digest_size = 1
222 block_size = 128
224 def __init__(self, digest_size: int):
226 if digest_size != 64:
227 raise ValueError("Digest size must be 64")
229 self._digest_size = digest_size
231 digest_size = utils.read_only_property("_digest_size")
234class BLAKE2s(HashAlgorithm):
235 name = "blake2s"
236 block_size = 64
237 _max_digest_size = 32
238 _min_digest_size = 1
240 def __init__(self, digest_size: int):
242 if digest_size != 32:
243 raise ValueError("Digest size must be 32")
245 self._digest_size = digest_size
247 digest_size = utils.read_only_property("_digest_size")