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) totp.verify(totp_value, time)
def add_otptoken(host, owner, *, otptype="hotp", digits=6, algo="sha1"): args = [ "ipa", "otptoken-add", "--owner", owner, "--type", otptype, "--digits", str(digits), "--algo", algo, "--no-qrcode", ] result = host.run_command(args) otpuid = re.search(r"Unique ID:\s*([a-z0-9-]*)\s+", result.stdout_text).group(1) otpuristr = re.search(r"URI:\s*(.*)\s+", result.stdout_text).group(1) otpuri = urlparse(otpuristr) assert otpuri.netloc == otptype query = parse_qs(otpuri.query) assert query["algorithm"][0] == algo.upper() assert query["digits"][0] == str(digits) key = base64.b32decode(query["secret"][0]) assert len(key) == 35 hashcls = getattr(hashes, algo.upper()) if otptype == "hotp": return otpuid, HOTP(key, digits, hashcls(), default_backend()) else: period = int(query["period"][0]) return otpuid, TOTP(key, digits, hashcls(), period, default_backend())
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 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 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_invalid_backend(): secret = b"12345678901234567890" pretend_backend = object() with raises_unsupported_algorithm(_Reasons.BACKEND_MISSING_INTERFACE): TOTP(secret, 8, hashes.SHA1(), 30, pretend_backend)
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 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 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 otp(): f = open('pass.txt', 'rb') key = f.read() #print(key) totp = TOTP(key, 8, SHA1(), 30, backend=default_backend()) time_value = time.time() totp_value = totp.generate(time_value) return totp_value
def test_verify_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.verify(totp_value, time) is 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 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 _get_mfa_token_pin(self): totp_key = base64.b32decode(self._mfa_token_seed) totp = TOTP(totp_key, 6, SHA1(), self._mfa_token_time_step, backend=default_backend(), enforce_key_length=False) time_value = time.time() return totp.generate(time_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 _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 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}"
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 _otp(self): """ Current one time password implementation, time-based "TOTP" https://cryptography.io/en/latest/hazmat/primitives/twofactor/ """ if not self._otp_enabled or len(self._otp_secret) < 1: raise ValueError("2FA/OTP is not enabled for this user") key = self._otp_secret.decode('hex') return TOTP(key, self.OTP_LENGTH, SHA512(), self.OTP_STEP, backend=default_backend())
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 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 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 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 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 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 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 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 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_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