def verify(self, otp_client): with open("otp", "rb") as f: key = f.read() totp = TOTP(key, 8, hashes.SHA1(), 30, backend=default_backend()) tval = time.time() otp_server = totp.generate(tval) return otp_server == otp_client
def test_floating_point_time_generate(self, backend): secret = b"12345678901234567890" time = 59.1 totp = TOTP(secret, 8, hashes.SHA1(), 30, backend) assert totp.generate(time) == b"94287082"
def test_generate_sha512(self, backend, params): secret = params["secret"] time = int(params["time"]) totp_value = params["totp"] totp = TOTP(secret, 8, hashes.SHA512(), 30, backend) assert totp.generate(time) == totp_value
def test_invalid_verify(self, backend): secret = b"12345678901234567890" time = 59 totp = TOTP(secret, 8, hashes.SHA1(), 30, backend) with pytest.raises(InvalidToken): totp.verify(b"12345678", time)
def test_verify_sha256(self, backend, params): secret = params["secret"] time = int(params["time"]) totp_value = params["totp"] totp = TOTP(secret, 8, hashes.SHA256(), 30, backend) assert totp.verify(totp_value, time) is None
def test_verify_totp_failure(skew): secret = generate_totp_secret() totp = TOTP(secret, TOTP_LENGTH, SHA1(), TOTP_INTERVAL, backend=default_backend()) value = totp.generate(time.time() + skew) assert not verify_totp(secret, value)
def generate_secret(): totp = TOTP( key=codecs.encode(string.ascii_letters, encoding="utf-8"), length=8, algorithm=SHA1(), time_step=ONE_WEEK_IN_SECONDS, backend=default_backend(), ) seed = int(time.time()) token = codecs.decode(totp.generate(seed), encoding="utf-8") return f"{token}-{seed}" # there are 2 small bugs below you'll have to fix before proceeding :)
def test_get_provisioning_uri(self, backend): secret = b"12345678901234567890" totp = TOTP(secret, 6, hashes.SHA1(), 30, backend=backend) assert totp.get_provisioning_uri("Alice Smith", None) == ( "otpauth://totp/Alice%20Smith?digits=6&secret=GEZDGNBVG" "Y3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&period=30") assert totp.get_provisioning_uri("Alice Smith", 'World') == ( "otpauth://totp/World:Alice%20Smith?digits=6&secret=GEZ" "DGNBVGY3TQOJQGEZDGNBVGY3TQOJQ&algorithm=SHA1&issuer=World" "&period=30")
def FakeToken(seed, salt=b'', refresh=30, info=b"fake-rsa-token"): kdf = PBKDF2HMAC( algorithm=SHA256(), length=32, salt=salt, iterations=100000, ) key = kdf.derive(seed) totp = TOTP(key, 8, SHA256(), refresh) while True: token_time = time.time() cur_epoch = int(token_time/refresh) next_time = (cur_epoch+1)*refresh yield (next_time-int(token_time), totp.generate(token_time))
def Totp(self, key): # simple constructor helper if not key: key = os.urandom(20) # == 160 bytes which is recommended totp = TOTP(key, asint(config.get('auth.multifactor.totp.length', 6)), SHA1(), asint(config.get('auth.multifactor.totp.time', 30)), backend=default_backend()) totp.key = key # for convenience, else you have to use `totp._hotp._key` return totp
def generate_totp_passcode(secret): """Generate TOTP passcode. :param bytes secret: A base32 encoded secret for TOTP authentication :returns: totp passcode as bytes """ if isinstance(secret, six.text_type): secret = secret.encode('utf-8') while len(secret) % 8 != 0: secret = secret + b'=' decoded = base64.b32decode(secret) totp = TOTP( decoded, 6, SHA1(), 30, backend=default_backend()) return totp.generate(timegm(datetime.utcnow().utctimetuple())).decode()
def test_2fa(self): # Disable 2FA even if already disabled data_request = {'operation': 'disable_2fa', 'args': {}} handler = self.request(data_request, role='receiver') yield handler.put() # Start enrollment for @FA data_request = {'operation': 'enable_2fa_step1', 'args': {}} handler = self.request(data_request, role='receiver') totp_secret = yield handler.put() # Attempt enrolling for 2FA with an invalid token data_request = { 'operation': 'enable_2fa_step2', 'args': { 'value': 'invalid_token' } } handler = self.request(data_request, role='receiver') self.assertFailure(handler.put(), errors.InvalidTwoFactorAuthCode) # Attempt enrolling for 2FA with a valid token totp = TOTP(base64.b32decode(totp_secret), 6, SHA1(), 30, default_backend()) current_token = totp.generate(time.time()).decode() data_request = { 'operation': 'enable_2fa_step2', 'args': { 'value': current_token } } handler = self.request(data_request, role='receiver') yield handler.put() data_request = {'operation': 'disable_2fa', 'args': {}} handler = self.request(data_request, role='receiver') yield handler.put()
def auth_helper(): def auth_check(ts): try: totp_obj.verify(totp.encode(), ts) tup = model.get_user_otp(username) if not tup: globalized.debug("Failed to get tup") return False last_totp, last_ts = tup if last_totp == totp and ts - last_ts < 30: globalized.debug("otp already used") return False except InvalidToken: globalized.debug("Invalid token") return False # If it fails to store we report failure globalized.debug("success, going to store totp and ts") return model.store_user_otp(username, totp, ts) secret = model.get_user_secret(username) if not secret: # Unknown user globalized.debug(f"Unkown user: {username}") return "??" from cryptography.hazmat.primitives.twofactor.totp import TOTP from cryptography.hazmat.primitives.twofactor import InvalidToken from cryptography.hazmat.primitives.hashes import SHA256 totp_obj = TOTP(secret, 6, SHA256(), 30) if auth_check(now) or auth_check(now - 30): return "OK" else: return "NO"
def generate_totp_uri(secret, email): """ Generate a Google authenticator compatible QR provisioning URI Args: secret: 16 character base32 secret email: Authenticator email address Return: URI for QR code: otpauth://totp/[email protected]?secret=JBSWY3DPEHPK3PXP&issuer=FrostyWeb """ if isinstance(secret, unicode): secret = secret.encode('utf-8') try: key = base64.b32decode(secret) totp = TOTP(key, 8, SHA1(), 30, backend=default_backend(), enforce_key_length=False) return totp.get_provisioning_uri(email, 'FrostyWeb') except TypeError: pass return None
def totp(self): """The implementation of Time-based One-Time Password algorithm. :rtype: cryptography.hazmat.primitives.twofactor.totp.TOTP """ return TOTP( self.secret_key, self.totp_length, self.totp_algorithm, self.totp_time_step, self.totp_backend)
def generate_totp_code(secret): """ Generate a Google authenticator compatible TOTP code Args: secret: 16 character base32 secret Return: code: 8 digit code that expires in 30 seconds """ if isinstance(secret, unicode): secret = secret.encode('utf-8') try: key = base64.b32decode(secret) totp = TOTP(key, 8, SHA1(), 30, backend=default_backend(), enforce_key_length=False) time_value = int(time.time()) totp_value = totp.generate(time_value) return totp_value except (ValueError, TypeError): pass return None
def init(self, accept_q): file_path = os.path.join(HYP3RARMOR_ROOT, "seed.txt") self.totp = TOTP(load_seed(file_path), TOTP_LENGTH, hashes.SHA256(), config.token_ttl, backend=default_backend()) super(IPBoundTokenNetMonitor, self).init(accept_q)
def get_otp(key): """ Generate One-Time Password from key """ missing_padding = len(key) % 8 if missing_padding != 0: key += '=' * (8 - missing_padding) try: byte_key = b32decode(key, casefold=True) except: return None totp = TOTP(byte_key, 6, SHA1(), 30, backend=default_backend(), enforce_key_length=False) return totp.generate(time()).decode()
def check_qrcode_credential(request): if request.method == 'POST': if not Method.objects.get(name='QRCode').status: return JsonResponse(create_msg_to_send(create_status_msg(400, 'QRCode authentication disabled!'), RASP_RSAPUB_KEY)) msg = json.loads(decrypt_msg(request.POST, RASP_ECCPUB_KEY)) msg = json.loads(msg) email = msg['identity'] if User.objects.filter(username=email).exists(): user = User.objects.get(username=email) else: return JsonResponse(create_msg_to_send(create_status_msg(400, 'User does not exist!'), RASP_RSAPUB_KEY)) # TODO: Permission validation (and perm.end_time > timezone.now()) perm = Permission.objects.get(user=user) if perm.state and perm.start_time < timezone.now(): credential = Credential.objects.get(user=user) if credential is not None and credential.status == 'valid': key = bytes.fromhex(credential.data) totp = TOTP(key, 8, SHA256(), 30, backend=default_backend()) try: totp.verify(msg['password'].encode(), time.time()) except InvalidToken: return JsonResponse(create_msg_to_send(create_status_msg(400, 'Authentication Failed!'), RASP_RSAPUB_KEY)) logs = Log.objects.select_related().filter(user=user).all().order_by('time_stamp').reverse() if logs: if logs[0].log_type == 'leave': log = Log(user=user, log_type='entry', time_stamp=timezone.now()) log.save() last_access = {'name': user.last_name, 'img': user.profile.photo.url} send_last_access(last_access) else: log = Log(user=user, log_type='leave', time_stamp=timezone.now()) log.save() else: log = Log(user=user, log_type='entry', time_stamp=timezone.now()) log.save() last_access = {'name': user.last_name, 'img': user.profile.photo.url} send_last_access(last_access) return JsonResponse(create_msg_to_send(create_status_msg(200, 'Authentication Successful', user.last_name.split()[0]), RASP_RSAPUB_KEY)) else: return JsonResponse(create_msg_to_send(create_status_msg(400, 'No permission!'), RASP_RSAPUB_KEY)) else: return JsonResponse(create_msg_to_send(create_status_msg(405, 'Only POST method is allowed!'), RASP_RSAPUB_KEY))
def _get_totp(secret): """ Returns a TOTP object for device provisioning and OTP validation. The TOTP object is instantiated with the default OTP parameters, per RFC6238: * SHA1 digest * 6-digit code * 30-second interval """ return TOTP(secret, TOTP_LENGTH, SHA1(), TOTP_INTERVAL, backend=default_backend())
def verify_totp_code(secret, code): """ Validate a Google authenticator compatible TOTP code Args: secret: 16 character base32 secret code: 8 digit code that expires in 30 seconds Return: True if validation successful """ if isinstance(secret, unicode): secret = secret.encode('utf-8') if isinstance(code, unicode): code = code.encode('utf-8') try: key = base64.b32decode(secret) totp = TOTP(key, 8, SHA1(), 30, backend=default_backend(), enforce_key_length=False) time_value = int(time.time()) totp.verify(code, time_value) return True except (ValueError, TypeError, InvalidToken): pass return None
def get_totp(secret, key_length, hash_algorithm, key_valid_duration): """Get the cryptography TOTP handler :param secret: bytes :param key_length: int length of totp key :param key_valid_duration: int duration each key is valid for """ return TOTP( secret, key_length, TOTP_HASH_ALGORITHMS[hash_algorithm](), key_valid_duration, backend=default_backend(), )
def get_otps(self): """ Calculate current OTPs for all accounts """ otps = {} for account, key in self._otp_keys.items(): missing_padding = len(key) % 8 if missing_padding != 0: key += '=' * (8 - missing_padding) try: byte_key = b32decode(key, casefold=True) except binascii.Error: otps[account] = "Error" break totp = TOTP(byte_key, 6, SHA1(), 30, backend=default_backend(), enforce_key_length=False) otp = totp.generate(time()).decode() otps[account] = otp return otps
""" Implementación de un sistema que valida tokens TOTP. Atención: Revisa cuidadosemente la hora del validador/Cliente. La mayoria de problemas con los tokens TOTP vienen por desfases temporales entre cliente y servidor RFC-6238 Time-based One-time Password (TOTP) """ import time import os from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.twofactor.totp import TOTP, InvalidToken from cryptography.hazmat.primitives.hashes import SHA1 key = b'abcdefghij' totp = TOTP(key, 6, SHA1(), 30, backend=default_backend()) token = input("Token?: ").encode() try: totp.verify(token, time.time()) print("Token Válido") except InvalidToken: print("Token Inválido")
from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.twofactor.totp import TOTP from cryptography.hazmat.primitives.hashes import SHA1 from cryptography.hazmat.primitives.twofactor import InvalidToken import pyqrcode key = os.urandom(16) counter = 1 time_value = time.time() issuer = 'GruPyPR' account_name = input('Your name: ') totp = TOTP(key, 6, SHA1(), 30, backend=default_backend()) uri = totp.get_provisioning_uri(account_name, issuer) url = pyqrcode.create(uri) print('Scan this!\n') url.svg('totp.svg', scale=8) webbrowser.open('totp.svg') while True: try: totp_value = bytes(input('Two factor password: '******'utf-8') totp.verify(totp_value, time.time()) print('You are authenticated!\n') except InvalidToken: print('You shall not pass!')
#!/usr/bin/env python3 """ Genera un QR TOTP compatible con Google Authenticator """ import webbrowser from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives.hashes import SHA1 from cryptography.hazmat.primitives.twofactor.totp import TOTP google_url = 'http://chart.googleapis.com/chart?chs=200x200&chld=M|0&cht=qr&chl=' cuenta = '*****@*****.**' expedida_por = None key = b'abcdefghij' totp = TOTP(key, 8, SHA1(), 30, backend=default_backend()) uri = totp.get_provisioning_uri(cuenta, expedida_por) url = '%s%s' % (google_url, uri) webbrowser.open(url)
def test_buffer_protocol(self, backend): key = bytearray(b"a long key with lots of entropy goes here") totp = TOTP(key, 8, hashes.SHA512(), 30, backend) time = 60 assert totp.generate(time) == b"53049576"
def verify_totp_code(user, code): totp = TOTP(bytes(user.secret), 6, SHA1(), 30, backend=default_backend()) return totp.verify(force_bytes(code), time.time())