def test_ignoring_spaces_in_secret(self): """ Check if spaces are skipped during generation of the token """ def chunks(original, size): """ Split original string into chunks sized as requested in ``size`` parameter. Returns iterator yielding single chunks. Similar to: http://stackoverflow.com/a/312464/548696 :param original: original string (almost any iterable really) :type original: str or unicode :param size: requested size of chunks :type size: int """ for i in six.moves.range(0, len(original), size): yield original[i:i + size] # Simple generation without spaces: secret = 'MFRGGZDFMZTWQ2LK' # Simple generation with spaces: secret_with_spaces = ' '.join(chunks(secret, 3)) # Check if was properly sliced: self.assertEqual(5, secret_with_spaces.count(' ')) # Both spaceless secret and secret with spaces should give the same self.assertEqual( get_hotp(secret, 1), get_hotp(secret_with_spaces, 1), )
def test_ignoring_spaces_in_secret(self): """ Check if spaces are skipped during generation of the token """ def chunks(original, size): """ Split original string into chunks sized as requested in ``size`` parameter. Returns iterator yielding single chunks. Similar to: http://stackoverflow.com/a/312464/548696 :param original: original string (almost any iterable really) :type original: str or unicode :param size: requested size of chunks :type size: int """ for i in six.moves.range(0, len(original), size): yield original[i:i+size] # Simple generation without spaces: secret = 'MFRGGZDFMZTWQ2LK' # Simple generation with spaces: secret_with_spaces = ' '.join(chunks(secret, 3)) # Check if was properly sliced: self.assertEqual(5, secret_with_spaces.count(' ')) # Both spaceless secret and secret with spaces should give the same self.assertEqual( get_hotp(secret, 1), get_hotp(secret_with_spaces, 1), )
def test_generation_for_different_intervals(self): """ Check if the HOTP changes with different intervals properly """ secret = b'MFRGGZDFMZTWQ2LK' self.assertEqual(get_hotp(secret, intervals_no=1), 765705) self.assertEqual(get_hotp(secret, intervals_no=2), 816065) self.assertEqual( get_hotp(secret, intervals_no=2, as_string=True), b'816065', )
def test_generating_totp_at_specific_clock(self): """ check if the totp can be generated for a specific clock which is basically the same as hotp """ secret = b'MFRGGZDFMZTWQ2LK' hotp = get_hotp(secret=secret, intervals_no=int(time.time())//30,) totp = get_totp(secret=secret, clock=None) self.assertEqual(hotp, totp) # hotp intervals minus 1 hotp = get_hotp(secret=secret, intervals_no=int(time.time())//30-1,) #totp 30 seconds in the past totp = get_totp(secret=secret, clock=(int(time.time())-30)) self.assertEqual(hotp, totp)
def test_validating_correct_hotp_after_exhaustion(self): """ Validating token created for old interval number should fail """ secret = b'MFRGGZDFMZTWQ2LK' # Act as if the given token was created for previous interval self.assertFalse(valid_hotp(get_hotp(secret, 123), secret, last=123))
def test_checking_hotp_validity_for_unicode_secret(self): """ Validity check should also work if secret passed to valid_hotp is unicode. """ secret = six.u('MFRGGZDFMZTWQ2LK') self.assertTrue(valid_hotp(get_hotp(secret, 123), secret))
def test_hotp_generation_from_bytes_secret(self): """ Test simple generation of HOTP token """ # Simple generation from bytes secret = b'MFRGGZDFMZTWQ2LK' self.assertEqual(get_hotp(secret, 1), 765705)
def test_hotp_generation_from_unicode_secret(self): """ Check if HOTP is properly generated for unicode secrets """ # Simple generation from unicode secret = six.u('MFRGGZDFMZTWQ2LK') self.assertEqual(get_hotp(secret, 1), 765705)
def test_validating_correct_hotp_as_totp(self): """ Check if valid TOTP will work as HOTP - should not work, unless for very big interval number (matching Unix epoch timestamp) """ secret = b'MFRGGZDFMZTWQ2LK' self.assertFalse(valid_totp(get_hotp(secret, 1), secret))
def generateOTP(user): secKey = base64.b32encode(os.urandom(10)).decode('utf-8') user.secKey = secKey db.session.commit() token = otp.get_hotp(secKey, intervals_no=3) html = render_template('frontpage/otp.html', token=token) subject = "OTP Verification for Updating Password" send_email(user.email, subject, html)
def test_validating_correct_hotp_as_totp(self): """ Check if valid TOTP will work as HOTP - should not work, unless for very big interval number (matching Unix epoch timestamp) """ secret = b'MFRGGZDFMZTWQ2LK' with timecop.freeze(time.time()): self.assertFalse(valid_totp(get_hotp(secret, 1), secret))
def test_generating_current_totp_and_validating(self): """ Check if TOTP generated for current time is the same as manually created HOTP for proper interval """ secret = b'MFRGGZDFMZTWQ2LK' hotp = get_hotp(secret=secret, intervals_no=int(time.time())//30,) totp = get_totp(secret=secret) self.assertEqual(hotp, totp)
def test_retrieving_proper_interval_from_validator(self): """ Check, if returns valid interval when checking the valid HOTP """ secret = b'MFRGGZDFMZTWQ2LK' totp = 713385 result = valid_hotp(totp, secret, last=1, trials=5) # Should be 4, as HOTP is valid for 4th interval self.assertEqual(result, 4) # Re-generate HOTP for this specific interval and check again self.assertEqual(get_hotp(secret, intervals_no=4), totp)
def test_generating_current_totp_as_string(self): """ Check if the TOTP also works seamlessly when generated as string """ secret = b'MFRGGZDFMZTWQ2LK' hotp = get_hotp( secret=secret, intervals_no=int(time.time())//30, as_string=True, ) totp = get_totp(secret=secret, as_string=True) self.assertEqual(hotp, totp)
def test_generating_totp_at_specific_clock(self): """ check if the totp can be generated for a specific clock which is basically the same as hotp """ secret = b'MFRGGZDFMZTWQ2LK' with timecop.freeze(time.time()): hotp = get_hotp( secret=secret, intervals_no=int(time.time()) // 30, ) totp = get_totp(secret=secret, clock=None) self.assertEqual(hotp, totp) # hotp intervals minus 1 hotp = get_hotp( secret=secret, intervals_no=int(time.time()) // 30 - 1, ) # totp 30 seconds in the past totp = get_totp(secret=secret, clock=(int(time.time()) - 30)) self.assertEqual(hotp, totp)
def test_generating_current_totp_as_string(self): """ Check if the TOTP also works seamlessly when generated as string """ secret = b'MFRGGZDFMZTWQ2LK' with timecop.freeze(time.time()): hotp = get_hotp( secret=secret, intervals_no=int(time.time()) // 30, as_string=True, ) totp = get_totp(secret=secret, as_string=True) self.assertEqual(hotp, totp)
def test_generating_current_totp_and_validating(self): """ Check if TOTP generated for current time is the same as manually created HOTP for proper interval """ secret = b'MFRGGZDFMZTWQ2LK' with timecop.freeze(time.time()): hotp = get_hotp( secret=secret, intervals_no=int(time.time()) // 30, ) totp = get_totp(secret=secret) self.assertEqual(hotp, totp)
def __call__(self, username, garbage=False, do_replay=False): # calc right values! from base64 import b32decode mode, secret, _ = TEST_USERS[username] if garbage: pw = b'\x12' * 32 if mode == USER_AUTH_HMAC else b'123x23' cnt = (self.tt if mode == USER_AUTH_TOTP else 0) elif mode == USER_AUTH_HMAC: assert len(self.psbt_hash) == 32 assert username == 'pw' cnt = 0 from hmac import HMAC key = calc_hmac_key(dev.serial) pw = HMAC(key, self.psbt_hash, sha256).digest() #print("\n pw=%s\n key=%s\npsbt=%s\nsalt=%s\n" % ( # b2a_hex(pw), # b2a_hex(key), # b2a_hex(self.psbt_hash), # b2a_hex(salt))) assert not do_replay else: if do_replay: if mode == USER_AUTH_TOTP: cnt = self.tt - 1 elif mode == USER_AUTH_HOTP: cnt = self.ht - 1 else: if mode == USER_AUTH_TOTP: cnt = self.tt self.tt += 1 elif mode == USER_AUTH_HOTP: cnt = self.ht self.ht += 1 pw = b'%06d' % get_hotp(secret, cnt) assert len(pw) in {6, 32} # no feedback from device at this point. dev.send_recv( CCProtocolPacker.user_auth(username.encode('ascii'), pw, totp_time=cnt))
def get(self, username, items=[]): if not username: return logger.error('a username was not passed in') try: document = db.collection.find({'username':username}, limit=1)[0] except IndexError: return logger.warning('could not find any matching users to delete') key = document['key'] step = int(document['step']) b32 = document['b32'] pin = otp.get_hotp(b32, intervals_no=step) password = "******" % (document['secret'], pin) if 'pin' in items: pyperclip.copy(pin) logger.info('pin copied to the clipboard') else: pyperclip.copy(password) logger.info('secret with generated pin has been copied to the clipboard') document['step'] = step + 1 db.collection.update(document)
parser.description = "Prints the TOTP auth code for the given secret. Can be either the raw secret string or a otpauth:// URI; the script will attempt to auto-detect which is given." parser.usage = "%prog [options] secret OR %prog [options] --stdin < secret.txt" parser.epilog = "Copyright (c) Mark Embling 2013" parser.add_option("--stdin", dest="stdin", action="store_true", default=False, help="Read the secret (raw secret or otpauth:// URI) from stdin [default: %default]") parser.add_option("--type", dest="type", choices=["TOTP", "HOTP"], default="TOTP", help="Token type (HOTP or TOTP). If a URI is provided, the type will be determined from there. [default: %default]") parser.add_option("--count", dest="count", type="int", default=1, help="Counter for HOTP [default: %default]") # parser.add_option("-d", "--digits", dest="digits", # choices=['6','8'], default='6', # help="Number of digits to display (6 or 8) [default: %default]") (options, args) = parser.parse_args() # Get the secret and type data = _get_data(options, args) (secret, type_) = _get_secret(data) if type_ is None: type_ = options.type # Get the token and print if type_.upper() == "HOTP": print(otp.get_hotp(secret, intervals_no=options.count, as_string=True)) else: print(otp.get_totp(secret, as_string=True))
def test_returning_hotp_as_string(self): """ Check if properly returns string when asked """ secret = b'MFRGGZDFMZTWQ2LK' self.assertEqual(get_hotp(secret, 1, as_string=True), b'765705')
def valid_guess_xy(secret, coord, guess): "test if correct answer given" num = xy_to_num(coord) return get_hotp(secret, num) == int(guess)
def test_checking_hotp_validity_without_range(self): """ Check if validating HOTP without giving any interval works properly """ secret = b'MFRGGZDFMZTWQ2LK' self.assertTrue(valid_hotp(get_hotp(secret, 123), secret))
def calc_values(secret): "Calculate all the tokens for a single page" return [get_hotp(secret, i, as_string=True) for i in range(NUM_CODES)]