hashes.py 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  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.
  4. from __future__ import annotations
  5. import abc
  6. import sys
  7. from cryptography.hazmat.bindings._rust import openssl as rust_openssl
  8. from cryptography.utils import Buffer
  9. __all__ = [
  10. "MD5",
  11. "SHA1",
  12. "SHA3_224",
  13. "SHA3_256",
  14. "SHA3_384",
  15. "SHA3_512",
  16. "SHA224",
  17. "SHA256",
  18. "SHA384",
  19. "SHA512",
  20. "SHA512_224",
  21. "SHA512_256",
  22. "SHAKE128",
  23. "SHAKE256",
  24. "SM3",
  25. "BLAKE2b",
  26. "BLAKE2s",
  27. "ExtendableOutputFunction",
  28. "Hash",
  29. "HashAlgorithm",
  30. "HashContext",
  31. "XOFHash",
  32. ]
  33. class HashAlgorithm(metaclass=abc.ABCMeta):
  34. @property
  35. @abc.abstractmethod
  36. def name(self) -> str:
  37. """
  38. A string naming this algorithm (e.g. "sha256", "md5").
  39. """
  40. @property
  41. @abc.abstractmethod
  42. def digest_size(self) -> int:
  43. """
  44. The size of the resulting digest in bytes.
  45. """
  46. @property
  47. @abc.abstractmethod
  48. def block_size(self) -> int | None:
  49. """
  50. The internal block size of the hash function, or None if the hash
  51. function does not use blocks internally (e.g. SHA3).
  52. """
  53. class HashContext(metaclass=abc.ABCMeta):
  54. @property
  55. @abc.abstractmethod
  56. def algorithm(self) -> HashAlgorithm:
  57. """
  58. A HashAlgorithm that will be used by this context.
  59. """
  60. @abc.abstractmethod
  61. def update(self, data: Buffer) -> None:
  62. """
  63. Processes the provided bytes through the hash.
  64. """
  65. @abc.abstractmethod
  66. def finalize(self) -> bytes:
  67. """
  68. Finalizes the hash context and returns the hash digest as bytes.
  69. """
  70. @abc.abstractmethod
  71. def copy(self) -> HashContext:
  72. """
  73. Return a HashContext that is a copy of the current context.
  74. """
  75. Hash = rust_openssl.hashes.Hash
  76. HashContext.register(Hash)
  77. XOFHash = rust_openssl.hashes.XOFHash
  78. class ExtendableOutputFunction(metaclass=abc.ABCMeta):
  79. """
  80. An interface for extendable output functions.
  81. """
  82. class SHA1(HashAlgorithm):
  83. name = "sha1"
  84. digest_size = 20
  85. block_size = 64
  86. def __eq__(self, other: object) -> bool:
  87. if not isinstance(other, SHA1):
  88. return NotImplemented
  89. return True
  90. class SHA512_224(HashAlgorithm): # noqa: N801
  91. name = "sha512-224"
  92. digest_size = 28
  93. block_size = 128
  94. def __eq__(self, other: object) -> bool:
  95. if not isinstance(other, SHA512_224):
  96. return NotImplemented
  97. return True
  98. class SHA512_256(HashAlgorithm): # noqa: N801
  99. name = "sha512-256"
  100. digest_size = 32
  101. block_size = 128
  102. def __eq__(self, other: object) -> bool:
  103. if not isinstance(other, SHA512_256):
  104. return NotImplemented
  105. return True
  106. class SHA224(HashAlgorithm):
  107. name = "sha224"
  108. digest_size = 28
  109. block_size = 64
  110. def __eq__(self, other: object) -> bool:
  111. if not isinstance(other, SHA224):
  112. return NotImplemented
  113. return True
  114. class SHA256(HashAlgorithm):
  115. name = "sha256"
  116. digest_size = 32
  117. block_size = 64
  118. def __eq__(self, other: object) -> bool:
  119. if not isinstance(other, SHA256):
  120. return NotImplemented
  121. return True
  122. class SHA384(HashAlgorithm):
  123. name = "sha384"
  124. digest_size = 48
  125. block_size = 128
  126. def __eq__(self, other: object) -> bool:
  127. if not isinstance(other, SHA384):
  128. return NotImplemented
  129. return True
  130. class SHA512(HashAlgorithm):
  131. name = "sha512"
  132. digest_size = 64
  133. block_size = 128
  134. def __eq__(self, other: object) -> bool:
  135. if not isinstance(other, SHA512):
  136. return NotImplemented
  137. return True
  138. class SHA3_224(HashAlgorithm): # noqa: N801
  139. name = "sha3-224"
  140. digest_size = 28
  141. block_size = None
  142. def __eq__(self, other: object) -> bool:
  143. if not isinstance(other, SHA3_224):
  144. return NotImplemented
  145. return True
  146. class SHA3_256(HashAlgorithm): # noqa: N801
  147. name = "sha3-256"
  148. digest_size = 32
  149. block_size = None
  150. def __eq__(self, other: object) -> bool:
  151. if not isinstance(other, SHA3_256):
  152. return NotImplemented
  153. return True
  154. class SHA3_384(HashAlgorithm): # noqa: N801
  155. name = "sha3-384"
  156. digest_size = 48
  157. block_size = None
  158. def __eq__(self, other: object) -> bool:
  159. if not isinstance(other, SHA3_384):
  160. return NotImplemented
  161. return True
  162. class SHA3_512(HashAlgorithm): # noqa: N801
  163. name = "sha3-512"
  164. digest_size = 64
  165. block_size = None
  166. def __eq__(self, other: object) -> bool:
  167. if not isinstance(other, SHA3_512):
  168. return NotImplemented
  169. return True
  170. class SHAKE128(HashAlgorithm, ExtendableOutputFunction):
  171. name = "shake128"
  172. block_size = None
  173. def __init__(self, digest_size: int):
  174. if not isinstance(digest_size, int):
  175. raise TypeError("digest_size must be an integer")
  176. if digest_size < 1:
  177. raise ValueError("digest_size must be a positive integer")
  178. self._digest_size = digest_size
  179. def __eq__(self, other: object) -> bool:
  180. if not isinstance(other, SHAKE128):
  181. return NotImplemented
  182. return self._digest_size == other._digest_size
  183. @property
  184. def digest_size(self) -> int:
  185. return self._digest_size
  186. @classmethod
  187. def xof(cls):
  188. return cls(sys.maxsize)
  189. class SHAKE256(HashAlgorithm, ExtendableOutputFunction):
  190. name = "shake256"
  191. block_size = None
  192. def __init__(self, digest_size: int):
  193. if not isinstance(digest_size, int):
  194. raise TypeError("digest_size must be an integer")
  195. if digest_size < 1:
  196. raise ValueError("digest_size must be a positive integer")
  197. self._digest_size = digest_size
  198. def __eq__(self, other: object) -> bool:
  199. if not isinstance(other, SHAKE256):
  200. return NotImplemented
  201. return self._digest_size == other._digest_size
  202. @property
  203. def digest_size(self) -> int:
  204. return self._digest_size
  205. @classmethod
  206. def xof(cls):
  207. return cls(sys.maxsize)
  208. class MD5(HashAlgorithm):
  209. name = "md5"
  210. digest_size = 16
  211. block_size = 64
  212. def __eq__(self, other: object) -> bool:
  213. if not isinstance(other, MD5):
  214. return NotImplemented
  215. return True
  216. class BLAKE2b(HashAlgorithm):
  217. name = "blake2b"
  218. _max_digest_size = 64
  219. _min_digest_size = 1
  220. block_size = 128
  221. def __init__(self, digest_size: int):
  222. if digest_size != 64:
  223. raise ValueError("Digest size must be 64")
  224. self._digest_size = digest_size
  225. def __eq__(self, other: object) -> bool:
  226. if not isinstance(other, BLAKE2b):
  227. return NotImplemented
  228. return self._digest_size == other._digest_size
  229. @property
  230. def digest_size(self) -> int:
  231. return self._digest_size
  232. class BLAKE2s(HashAlgorithm):
  233. name = "blake2s"
  234. block_size = 64
  235. _max_digest_size = 32
  236. _min_digest_size = 1
  237. def __init__(self, digest_size: int):
  238. if digest_size != 32:
  239. raise ValueError("Digest size must be 32")
  240. self._digest_size = digest_size
  241. def __eq__(self, other: object) -> bool:
  242. if not isinstance(other, BLAKE2s):
  243. return NotImplemented
  244. return self._digest_size == other._digest_size
  245. @property
  246. def digest_size(self) -> int:
  247. return self._digest_size
  248. class SM3(HashAlgorithm):
  249. name = "sm3"
  250. digest_size = 32
  251. block_size = 64
  252. def __eq__(self, other: object) -> bool:
  253. if not isinstance(other, SM3):
  254. return NotImplemented
  255. return True