hmac.py 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  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. import typing
  5. from cryptography import utils
  6. from cryptography.exceptions import (
  7. AlreadyFinalized,
  8. )
  9. from cryptography.hazmat.backends.openssl.hmac import _HMACContext
  10. from cryptography.hazmat.primitives import hashes
  11. class HMAC(hashes.HashContext):
  12. _ctx: typing.Optional[_HMACContext]
  13. def __init__(
  14. self,
  15. key: bytes,
  16. algorithm: hashes.HashAlgorithm,
  17. backend: typing.Any = None,
  18. ctx=None,
  19. ):
  20. if not isinstance(algorithm, hashes.HashAlgorithm):
  21. raise TypeError("Expected instance of hashes.HashAlgorithm.")
  22. self._algorithm = algorithm
  23. self._key = key
  24. if ctx is None:
  25. from cryptography.hazmat.backends.openssl.backend import (
  26. backend as ossl,
  27. )
  28. self._ctx = ossl.create_hmac_ctx(key, self.algorithm)
  29. else:
  30. self._ctx = ctx
  31. @property
  32. def algorithm(self) -> hashes.HashAlgorithm:
  33. return self._algorithm
  34. def update(self, data: bytes) -> None:
  35. if self._ctx is None:
  36. raise AlreadyFinalized("Context was already finalized.")
  37. utils._check_byteslike("data", data)
  38. self._ctx.update(data)
  39. def copy(self) -> "HMAC":
  40. if self._ctx is None:
  41. raise AlreadyFinalized("Context was already finalized.")
  42. return HMAC(
  43. self._key,
  44. self.algorithm,
  45. ctx=self._ctx.copy(),
  46. )
  47. def finalize(self) -> bytes:
  48. if self._ctx is None:
  49. raise AlreadyFinalized("Context was already finalized.")
  50. digest = self._ctx.finalize()
  51. self._ctx = None
  52. return digest
  53. def verify(self, signature: bytes) -> None:
  54. utils._check_bytes("signature", signature)
  55. if self._ctx is None:
  56. raise AlreadyFinalized("Context was already finalized.")
  57. ctx, self._ctx = self._ctx, None
  58. ctx.verify(signature)