hashes.py 6.1 KB

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