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