hashes.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. from cryptography.hazmat.bindings._rust import openssl as rust_openssl
  7. from cryptography.utils import Buffer
  8. __all__ = [
  9. "MD5",
  10. "SHA1",
  11. "SHA3_224",
  12. "SHA3_256",
  13. "SHA3_384",
  14. "SHA3_512",
  15. "SHA224",
  16. "SHA256",
  17. "SHA384",
  18. "SHA512",
  19. "SHA512_224",
  20. "SHA512_256",
  21. "SHAKE128",
  22. "SHAKE256",
  23. "SM3",
  24. "BLAKE2b",
  25. "BLAKE2s",
  26. "ExtendableOutputFunction",
  27. "Hash",
  28. "HashAlgorithm",
  29. "HashContext",
  30. "XOFHash",
  31. ]
  32. class HashAlgorithm(metaclass=abc.ABCMeta):
  33. @property
  34. @abc.abstractmethod
  35. def name(self) -> str:
  36. """
  37. A string naming this algorithm (e.g. "sha256", "md5").
  38. """
  39. @property
  40. @abc.abstractmethod
  41. def digest_size(self) -> int:
  42. """
  43. The size of the resulting digest in bytes.
  44. """
  45. @property
  46. @abc.abstractmethod
  47. def block_size(self) -> int | None:
  48. """
  49. The internal block size of the hash function, or None if the hash
  50. function does not use blocks internally (e.g. SHA3).
  51. """
  52. class HashContext(metaclass=abc.ABCMeta):
  53. @property
  54. @abc.abstractmethod
  55. def algorithm(self) -> HashAlgorithm:
  56. """
  57. A HashAlgorithm that will be used by this context.
  58. """
  59. @abc.abstractmethod
  60. def update(self, data: Buffer) -> None:
  61. """
  62. Processes the provided bytes through the hash.
  63. """
  64. @abc.abstractmethod
  65. def finalize(self) -> bytes:
  66. """
  67. Finalizes the hash context and returns the hash digest as bytes.
  68. """
  69. @abc.abstractmethod
  70. def copy(self) -> HashContext:
  71. """
  72. Return a HashContext that is a copy of the current context.
  73. """
  74. Hash = rust_openssl.hashes.Hash
  75. HashContext.register(Hash)
  76. XOFHash = rust_openssl.hashes.XOFHash
  77. class ExtendableOutputFunction(metaclass=abc.ABCMeta):
  78. """
  79. An interface for extendable output functions.
  80. """
  81. class SHA1(HashAlgorithm):
  82. name = "sha1"
  83. digest_size = 20
  84. block_size = 64
  85. class SHA512_224(HashAlgorithm): # noqa: N801
  86. name = "sha512-224"
  87. digest_size = 28
  88. block_size = 128
  89. class SHA512_256(HashAlgorithm): # noqa: N801
  90. name = "sha512-256"
  91. digest_size = 32
  92. block_size = 128
  93. class SHA224(HashAlgorithm):
  94. name = "sha224"
  95. digest_size = 28
  96. block_size = 64
  97. class SHA256(HashAlgorithm):
  98. name = "sha256"
  99. digest_size = 32
  100. block_size = 64
  101. class SHA384(HashAlgorithm):
  102. name = "sha384"
  103. digest_size = 48
  104. block_size = 128
  105. class SHA512(HashAlgorithm):
  106. name = "sha512"
  107. digest_size = 64
  108. block_size = 128
  109. class SHA3_224(HashAlgorithm): # noqa: N801
  110. name = "sha3-224"
  111. digest_size = 28
  112. block_size = None
  113. class SHA3_256(HashAlgorithm): # noqa: N801
  114. name = "sha3-256"
  115. digest_size = 32
  116. block_size = None
  117. class SHA3_384(HashAlgorithm): # noqa: N801
  118. name = "sha3-384"
  119. digest_size = 48
  120. block_size = None
  121. class SHA3_512(HashAlgorithm): # noqa: N801
  122. name = "sha3-512"
  123. digest_size = 64
  124. block_size = None
  125. class SHAKE128(HashAlgorithm, ExtendableOutputFunction):
  126. name = "shake128"
  127. block_size = None
  128. def __init__(self, digest_size: int):
  129. if not isinstance(digest_size, int):
  130. raise TypeError("digest_size must be an integer")
  131. if digest_size < 1:
  132. raise ValueError("digest_size must be a positive integer")
  133. self._digest_size = digest_size
  134. @property
  135. def digest_size(self) -> int:
  136. return self._digest_size
  137. class SHAKE256(HashAlgorithm, ExtendableOutputFunction):
  138. name = "shake256"
  139. block_size = None
  140. def __init__(self, digest_size: int):
  141. if not isinstance(digest_size, int):
  142. raise TypeError("digest_size must be an integer")
  143. if digest_size < 1:
  144. raise ValueError("digest_size must be a positive integer")
  145. self._digest_size = digest_size
  146. @property
  147. def digest_size(self) -> int:
  148. return self._digest_size
  149. class MD5(HashAlgorithm):
  150. name = "md5"
  151. digest_size = 16
  152. block_size = 64
  153. class BLAKE2b(HashAlgorithm):
  154. name = "blake2b"
  155. _max_digest_size = 64
  156. _min_digest_size = 1
  157. block_size = 128
  158. def __init__(self, digest_size: int):
  159. if digest_size != 64:
  160. raise ValueError("Digest size must be 64")
  161. self._digest_size = digest_size
  162. @property
  163. def digest_size(self) -> int:
  164. return self._digest_size
  165. class BLAKE2s(HashAlgorithm):
  166. name = "blake2s"
  167. block_size = 64
  168. _max_digest_size = 32
  169. _min_digest_size = 1
  170. def __init__(self, digest_size: int):
  171. if digest_size != 32:
  172. raise ValueError("Digest size must be 32")
  173. self._digest_size = digest_size
  174. @property
  175. def digest_size(self) -> int:
  176. return self._digest_size
  177. class SM3(HashAlgorithm):
  178. name = "sm3"
  179. digest_size = 32
  180. block_size = 64