totp.py 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  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. from cryptography.exceptions import UnsupportedAlgorithm, _Reasons
  6. from cryptography.hazmat.backends import _get_backend
  7. from cryptography.hazmat.backends.interfaces import HMACBackend
  8. from cryptography.hazmat.primitives import constant_time
  9. from cryptography.hazmat.primitives.twofactor import InvalidToken
  10. from cryptography.hazmat.primitives.twofactor.hotp import HOTP
  11. from cryptography.hazmat.primitives.twofactor.utils import _generate_uri
  12. class TOTP(object):
  13. def __init__(
  14. self,
  15. key,
  16. length,
  17. algorithm,
  18. time_step,
  19. backend=None,
  20. enforce_key_length=True,
  21. ):
  22. backend = _get_backend(backend)
  23. if not isinstance(backend, HMACBackend):
  24. raise UnsupportedAlgorithm(
  25. "Backend object does not implement HMACBackend.",
  26. _Reasons.BACKEND_MISSING_INTERFACE,
  27. )
  28. self._time_step = time_step
  29. self._hotp = HOTP(key, length, algorithm, backend, enforce_key_length)
  30. def generate(self, time):
  31. counter = int(time / self._time_step)
  32. return self._hotp.generate(counter)
  33. def verify(self, totp, time):
  34. if not constant_time.bytes_eq(self.generate(time), totp):
  35. raise InvalidToken("Supplied TOTP value does not match.")
  36. def get_provisioning_uri(self, account_name, issuer):
  37. return _generate_uri(
  38. self._hotp,
  39. "totp",
  40. account_name,
  41. issuer,
  42. [("period", int(self._time_step))],
  43. )