hashes.py 5.0 KB

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