def test_25_sha256_token(self): # taken from https://tools.ietf.org/html/rfc6238#appendix-B # sha256 with a 20 byte seed serial = "sha25T" db_token = Token(serial, tokentype="totp") db_token.save() token = TotpTokenClass(db_token) token.set_otpkey(binascii.hexlify("12345678901234567890")) token.set_hashlib("sha256") token.set_otplen(8) token.save() # get it from the database again # | 1111111111 | 2005-03-18 | 00000000023523ED | 67062674 | SHA256 | db_token = Token.query.filter_by(serial=serial).first() token = TotpTokenClass(db_token) r = token.check_otp("67062674", options={"initTime": 1111111111}) self.assertTrue(r) # sha256 with a 32 byte seed serial = "sha256" db_token = Token(serial, tokentype="totp") db_token.save() token = TotpTokenClass(db_token) token.set_otpkey(binascii.hexlify("12345678901234567890123456789012")) token.set_hashlib("sha256") token.set_otplen(8) token.save() db_token = Token.query.filter_by(serial=serial).first() token = TotpTokenClass(db_token) r = token.check_otp("67062674", options={"initTime": 1111111111}) self.assertTrue(r) # sha512 with a 20 byte seed serial = "sha512" db_token = Token(serial, tokentype="totp") db_token.save() token = TotpTokenClass(db_token) token.set_otpkey(binascii.hexlify("12345678901234567890")) token.set_hashlib("sha512") token.set_otplen(8) token.save() db_token = Token.query.filter_by(serial=serial).first() token = TotpTokenClass(db_token) r = token.check_otp("99943326", options={"initTime": 1111111111}) self.assertTrue(r) # sha512 with a 64byte seed serial = "sha512b" db_token = Token(serial, tokentype="totp") db_token.save() token = TotpTokenClass(db_token) token.set_otpkey(binascii.hexlify( "1234567890123456789012345678901234567890123456789012345678901234")) token.set_hashlib("sha512") token.set_otplen(8) token.save() db_token = Token.query.filter_by(serial=serial).first() token = TotpTokenClass(db_token) r = token.check_otp("93441116", options={"initTime": 1234567890}) self.assertTrue(r)
def test_25_sha256_token(self): # taken from https://tools.ietf.org/html/rfc6238#appendix-B # sha256 with a 20 byte seed serial = "sha25T" db_token = Token(serial, tokentype="totp") db_token.save() token = TotpTokenClass(db_token) token.set_otpkey(binascii.hexlify(b"12345678901234567890")) token.set_hashlib("sha256") token.set_otplen(8) token.save() # get it from the database again # | 1111111111 | 2005-03-18 | 00000000023523ED | 67062674 | SHA256 | db_token = Token.query.filter_by(serial=serial).first() token = TotpTokenClass(db_token) r = token.check_otp("67062674", options={"initTime": 1111111111}) self.assertTrue(r) # sha256 with a 32 byte seed serial = "sha256" db_token = Token(serial, tokentype="totp") db_token.save() token = TotpTokenClass(db_token) token.set_otpkey(binascii.hexlify(b"12345678901234567890123456789012")) token.set_hashlib("sha256") token.set_otplen(8) token.save() db_token = Token.query.filter_by(serial=serial).first() token = TotpTokenClass(db_token) r = token.check_otp("67062674", options={"initTime": 1111111111}) self.assertTrue(r) # sha512 with a 20 byte seed serial = "sha512" db_token = Token(serial, tokentype="totp") db_token.save() token = TotpTokenClass(db_token) token.set_otpkey(binascii.hexlify(b"12345678901234567890")) token.set_hashlib("sha512") token.set_otplen(8) token.save() db_token = Token.query.filter_by(serial=serial).first() token = TotpTokenClass(db_token) r = token.check_otp("99943326", options={"initTime": 1111111111}) self.assertTrue(r) # sha512 with a 64byte seed serial = "sha512b" db_token = Token(serial, tokentype="totp") db_token.save() token = TotpTokenClass(db_token) token.set_otpkey(binascii.hexlify( b"1234567890123456789012345678901234567890123456789012345678901234")) token.set_hashlib("sha512") token.set_otplen(8) token.save() db_token = Token.query.filter_by(serial=serial).first() token = TotpTokenClass(db_token) r = token.check_otp("93441116", options={"initTime": 1234567890}) self.assertTrue(r)
def test_26_is_previous_otp(self): # check if the OTP was used previously serial = "previous" db_token = Token(serial, tokentype="totp") db_token.save() token = TotpTokenClass(db_token) token.set_otpkey(self.otpkey) token.set_hashlib("sha1") token.set_otplen(6) # Authenticate with the current OTP value counter = token._time2counter(time.time(), timeStepping=30) otp_now = token._calc_otp(counter) r = token.check_otp(otp_now, window=180) self.assertEqual(r, counter) # Now we try several is_previous_otp and the timeShift must stay the same! ts0 = float(token.get_tokeninfo("timeShift")) self.assertTrue(-181 < ts0 < 181) # Too old r = token.is_previous_otp(token._calc_otp(counter - 3)) self.assertEqual(r, False) ts = float(token.get_tokeninfo("timeShift")) self.assertEqual(ts, ts0) # The same OTP value r = token.is_previous_otp(otp_now) self.assertEqual(r, True) ts = float(token.get_tokeninfo("timeShift")) self.assertEqual(ts, ts0) # Future value r = token.is_previous_otp(token._calc_otp(counter + 8)) self.assertEqual(r, False) ts = float(token.get_tokeninfo("timeShift")) self.assertEqual(ts, ts0)
def test_25_sha256_token(self): # taken from https://tools.ietf.org/html/rfc6238#appendix-B serial = "sha25T" db_token = Token(serial, tokentype="hotp") db_token.save() token = TotpTokenClass(db_token) token.set_otpkey(binascii.hexlify("12345678901234567890")) token.set_hashlib("sha256") token.set_otplen(8) token.set_otp_count(0x00000000023523ED - 2) token.save() # get it from the database again # | 1111111111 | 2005-03-18 | 00000000023523ED | 67062674 | SHA256 | db_token = Token.query.filter_by(serial=serial).first() token = TotpTokenClass(db_token) r = token.check_otp("67062674", options={"initTime": 1111111111}) self.assertTrue(r)
def test_22_autosync(self): db_token = Token.query.filter_by(serial=self.serial1).first() token = TotpTokenClass(db_token) set_privacyidea_config("AutoResync", True) token.update({"otpkey": self.otpkey, "otplen": 6}) token.token.count = 47251640 token.set_sync_window(10) # counter = 47251649 => otp = 705493, is out of sync r = token.check_otp(anOtpVal="705493", window=30, options={"initTime": 47251644 * 30}) self.assertTrue(r == -1, r) # counter = 47251650 => otp = 389836, will be autosynced. r = token.check_otp(anOtpVal="589836", window=30, options={"initTime": 47251645 * 30}) self.assertTrue(r == 47251650, r) # Autosync with a gap in the next otp value will fail token.token.count = 47251640 # Just try some bullshit config value set_privacyidea_config("AutoResyncTimeout", "totally not a number") # counter = 47251648 => otp = 032819, is out of sync r = token.check_otp(anOtpVal="032819", window=30, options={"initTime": 47251645 * 30}) self.assertTrue(r == -1, r) # counter = 47251650 => otp = 589836, will NOT _autosync r = token.check_otp(anOtpVal="589836", window=30, options={"initTime": 47251645 * 30}) self.assertTrue(r == -1, r) # TOTP has no dueDate / AutoResyncTimeout # No _autosync set_privacyidea_config("AutoResync", False) token.token.count = 47251640 token.set_sync_window(10) # counter = 47251649 => otp = 705493, is out of sync r = token.check_otp(anOtpVal="705493", window=30, options={"initTime": 47251644 * 30}) self.assertTrue(r == -1, r) # counter = 47251650 => otp = 389836, will not get autosynced. r = token.check_otp(anOtpVal="589836", window=30, options={"initTime": 47251645 * 30}) self.assertTrue(r == -1, r)
def test_22_autosync(self): db_token = Token.query.filter_by(serial=self.serial1).first() token = TotpTokenClass(db_token) set_privacyidea_config("AutoResync", True) token.update({"otpkey": self.otpkey, "otplen": 6}) token.token.count = 47251640 token.set_sync_window(10) # counter = 47251649 => otp = 705493, is out of sync r = token.check_otp(anOtpVal="705493", window=30, options={"initTime": 47251644 * 30}) self.assertTrue(r == -1, r) # counter = 47251650 => otp = 389836, will be autosynced. r = token.check_otp(anOtpVal="589836", window=30, options={"initTime": 47251645 * 30 }) self.assertTrue(r == 47251650, r) # Autosync with a gap in the next otp value will fail token.token.count = 47251640 # Just try some bullshit config value set_privacyidea_config("AutoResyncTimeout", "totally not a number") # counter = 47251648 => otp = 032819, is out of sync r = token.check_otp(anOtpVal="032819", window=30, options={"initTime": 47251645 * 30 }) self.assertTrue(r == -1, r) # counter = 47251650 => otp = 589836, will NOT _autosync r = token.check_otp(anOtpVal="589836", window=30, options={"initTime": 47251645 * 30 }) self.assertTrue(r == -1, r) # TOTP has no dueDate / AutoResyncTimeout # No _autosync set_privacyidea_config("AutoResync", False) token.token.count = 47251640 token.set_sync_window(10) # counter = 47251649 => otp = 705493, is out of sync r = token.check_otp(anOtpVal="705493", window=30, options={"initTime": 47251644 * 30}) self.assertTrue(r == -1, r) # counter = 47251650 => otp = 389836, will not get autosynced. r = token.check_otp(anOtpVal="589836", window=30, options={"initTime": 47251645 * 30 }) self.assertTrue(r == -1, r)
def test_19_pin_otp_functions(self): db_token = Token.query.filter_by(serial=self.serial1).first() db_token.set_pin("test") token = TotpTokenClass(db_token) # check OTP according to RFC 4226 token.update({"otpkey": self.otpkey}) self.assertTrue(db_token.otplen == 6, 6) set_prepend_pin() res, pin, otp = token.split_pin_pass("test123456") self.assertTrue(pin == "test", pin) self.assertTrue(otp == "123456", otp) self.assertTrue(token.check_pin(pin), pin) # get the OTP value for counter 1417549521 res = token.get_otp(time_seconds=1417549521) self.assertTrue(res[0] == 1, res) self.assertTrue(res[2] == "589836", res) check = token.check_otp("722053", counter=47251647) # The OTP 722053 is of counter 47251647 self.assertTrue(check == 47251647, check) # The tokenclass saves the counter to the database self.assertTrue(token.token.count == 47251647, token.token.count) check = token.check_otp("705493", counter=47251648) # The OTP 705493 is of counter 47251649, but it matches also. self.assertTrue(check == 47251649, check) # successful authentication res = token.authenticate("test589836") # This is the OTP value of the counter=47251650 self.assertTrue(res == (True, 47251650, None), res) # try the same OTP value again will fail! res = token.authenticate("test589836") # This is the OTP value of the counter=47251650 self.assertTrue(res == (True, -1, None), res) res = token.get_multi_otp() self.assertTrue(res[0] is False, res) token.update({"otpkey": self.otpkey, "otplen": 6, "timeShift": 0}) token.token.count = 0 res = token.get_multi_otp(count=5) self.assertTrue(res[0], res) self.assertTrue(res[1] == "OK", res) self.assertTrue(len(res[2].get("otp")) == 5, res[2].get("otp")) # Simulate the server time res = token.get_multi_otp(count=5, timestamp=47251644 * 30) self.assertTrue(res[0], res) self.assertTrue(res[1] == "OK", res) self.assertTrue(len(res[2].get("otp")) == 5, res[2].get("otp")) self.assertTrue(47251648 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47251647 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47251646 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47251645 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47251644 in res[2].get("otp"), res[2].get("otp")) # Simulate the server time res = token.get_multi_otp(count=5, curTime=datetime.datetime(2014, 12,12)) self.assertTrue(res[0], res) self.assertTrue(res[1] == "OK", res) self.assertTrue(len(res[2].get("otp")) == 5, res[2].get("otp")) self.assertTrue(47278080 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47278081 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47278082 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47278083 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47278084 in res[2].get("otp"), res[2].get("otp")) # do some failing otp checks token.token.otplen = "invalid otp counter" self.assertRaises(Exception, token.check_otp, "123456") token.token.otplen = 0 # Previous OTP value used again token.token.otplen = 6 #token.token.count = 47251640 # The OTP for this counter was already presented to the server token.token.count = 47251648 # 47251647 -> 722053 res = token.check_otp("722053", options={"initTime": 47251649 * 30}) #self.assertTrue(res == 47251647, res) self.assertTrue(res == -1, res) # simple get_otp of current time r = token.get_otp() self.assertTrue(r > 47251648, r) r = token.get_otp(current_time=datetime.datetime.now()) self.assertTrue(r > 47251648, r)
def test_04_base_methods(self): db_token = Token.query.filter_by(serial=self.serial1).first() token = TotpTokenClass(db_token) self.assertTrue(token.check_otp("123456", 1, 10) == -1) c = token.create_challenge("transactionid") self.assertTrue(c[0], c) self.assertTrue("transactionid" in c[2], c) # set the description token.set_description("something new") self.assertTrue(token.token.description == "something new", token.token) # set defaults token.set_defaults() self.assertTrue(token.token.otplen == 6) self.assertTrue(token.token.sync_window == 1000) token.resync("1234", "3456") token.token.count_window = 17 self.assertTrue(token.get_otp_count_window() == 17) token.token.count = 18 self.assertTrue(token.get_otp_count() == 18) token.token.active = False self.assertTrue(token.is_active() is False) token.token.failcount = 7 self.assertTrue(token.get_failcount() == 7) token.set_failcount(8) self.assertTrue(token.token.failcount == 8) token.token.maxfail = 12 self.assertTrue(token.get_max_failcount() == 12) self.assertTrue(token.get_user_id() == token.token.user_id) self.assertTrue(token.get_serial() == "SE123456", token.token.serial) self.assertTrue(token.get_tokentype() == "totp", token.token.tokentype) token.set_so_pin("sopin") token.set_user_pin("userpin") token.set_otpkey(self.otpkey) token.set_otplen(8) token.set_otp_count(1000) self.assertTrue(len(token.token.so_pin) == 32, token.token.so_pin) self.assertTrue(len(token.token.user_pin) == 32, token.token.user_pin) self.assertTrue(len(token.token.key_enc) == 192, token.token.key_enc) self.assertTrue(token.get_otplen() == 8) self.assertTrue(token.token.count == 1000, token.token.count) token.set_maxfail(1000) self.assertTrue(token.token.maxfail == 1000) token.set_count_window(52) self.assertTrue(token.get_count_window() == 52) token.set_sync_window(53) self.assertTrue(token.get_sync_window() == 53)
def test_19_pin_otp_functions(self): db_token = Token.query.filter_by(serial=self.serial1).first() db_token.set_pin("test") token = TotpTokenClass(db_token) # check OTP according to RFC 4226 token.update({"otpkey": self.otpkey}) self.assertTrue(db_token.otplen == 6, 6) set_prepend_pin() res, pin, otp = token.split_pin_pass("test123456") self.assertTrue(pin == "test", pin) self.assertTrue(otp == "123456", otp) self.assertTrue(token.check_pin(pin), pin) # get the OTP value for counter 1417549521 res = token.get_otp(time_seconds=1417549521) self.assertTrue(res[0] == 1, res) self.assertTrue(res[2] == "589836", res) check = token.check_otp("722053", counter=47251647) # The OTP 722053 is of counter 47251647 self.assertTrue(check == 47251647, check) # The tokenclass saves the counter to the database self.assertTrue(token.token.count == 47251647, token.token.count) check = token.check_otp("705493", counter=47251648) # The OTP 705493 is of counter 47251649, but it matches also. self.assertTrue(check == 47251649, check) # successful authentication res = token.authenticate("test589836") # This is the OTP value of the counter=47251650 self.assertTrue(res == (True, 47251650, None), res) # try the same OTP value again will fail! res = token.authenticate("test589836") # This is the OTP value of the counter=47251650 self.assertTrue(res == (True, -1, None), res) res = token.get_multi_otp() self.assertTrue(res[0] is False, res) token.update({"otpkey": self.otpkey, "otplen": 6}) token.token.count = 0 res = token.get_multi_otp(count=5) self.assertTrue(res[0], res) self.assertTrue(res[1] == "OK", res) self.assertTrue(len(res[2].get("otp")) == 5, res[2].get("otp")) # Simulate the server time res = token.get_multi_otp(count=5, timestamp=47251644 * 30) self.assertTrue(res[0], res) self.assertTrue(res[1] == "OK", res) self.assertTrue(len(res[2].get("otp")) == 5, res[2].get("otp")) self.assertTrue(47251648 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47251647 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47251646 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47251645 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47251644 in res[2].get("otp"), res[2].get("otp")) # Simulate the server time res = token.get_multi_otp(count=5, curTime=datetime.datetime(2014, 12,12)) self.assertTrue(res[0], res) self.assertTrue(res[1] == "OK", res) self.assertTrue(len(res[2].get("otp")) == 5, res[2].get("otp")) self.assertTrue(47278080 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47278081 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47278082 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47278083 in res[2].get("otp"), res[2].get("otp")) self.assertTrue(47278084 in res[2].get("otp"), res[2].get("otp")) # do some failing otp checks token.token.otplen = "invalid otp counter" self.assertRaises(Exception, token.check_otp, "123456") token.token.otplen = 0 # Previous OTP value used again token.token.otplen = 6 #token.token.count = 47251640 # The OTP for this counter was already presented to the server token.token.count = 47251648 # 47251647 -> 722053 res = token.check_otp("722053", options={"initTime": 47251649 * 30}) #self.assertTrue(res == 47251647, res) self.assertTrue(res == -1, res) # simple get_otp of current time r = token.get_otp() self.assertTrue(r > 47251648, r) r = token.get_otp(current_time=datetime.datetime.now()) self.assertTrue(r > 47251648, r)