Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,9 @@ if(BUILD_TESTS)
target_link_libraries(test_all PRIVATE hmac_cpp gtest_main)
target_include_directories(test_all PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
add_test(NAME test_all COMMAND test_all)

add_executable(test_totp test_totp.cpp)
target_link_libraries(test_totp PRIVATE hmac_cpp gtest_main)
target_include_directories(test_totp PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
add_test(NAME test_totp COMMAND test_totp)
endif()
2 changes: 1 addition & 1 deletion scripts/run_tests.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -e
cmake -S . -B build -DBUILD_TESTS=ON -DCMAKE_CXX_STANDARD=${CXX_STANDARD:-11}
cmake --build build
cmake --build build --target test_all test_totp
cd build
ctest --output-on-failure
51 changes: 27 additions & 24 deletions test_totp.cpp
Original file line number Diff line number Diff line change
@@ -1,36 +1,39 @@
#include "hmac_cpp/hmac_utils.hpp"
#include <cassert>
#include <gtest/gtest.h>
#include <limits>
#include <iostream>
#include "hmac_cpp/hmac_utils.hpp"

int main() {
TEST(TotpBoundaryTest, EarlyTimestampValidatesCounterZero) {
std::string key = "12345678901234567890";
int digits = 6;
uint64_t period = 30;
uint64_t early_timestamp = 5; // less than one period
int token = hmac::get_hotp_code(key.data(), key.size(), 0, digits, hmac::TypeHash::SHA1);
EXPECT_TRUE(hmac::is_totp_token_valid(token, key.data(), key.size(), early_timestamp, period, digits, hmac::TypeHash::SHA1));
}

// Token generated for counter = 0 should be valid at early timestamp
int token_counter0 = hmac::get_hotp_code(key.data(), key.size(), 0, digits, hmac::TypeHash::SHA1);
bool valid = hmac::is_totp_token_valid(token_counter0, key.data(), key.size(), early_timestamp, period, digits, hmac::TypeHash::SHA1);
assert(valid);

// Token from max counter should NOT be considered valid when timestamp is in the first period
TEST(TotpBoundaryTest, MaxCounterInvalidAtEarlyTimestamp) {
std::string key = "12345678901234567890";
int digits = 6;
uint64_t period = 30;
uint64_t early_timestamp = 5;
uint64_t max_counter = std::numeric_limits<uint64_t>::max();
int token_max = hmac::get_hotp_code(key.data(), key.size(), max_counter, digits, hmac::TypeHash::SHA1);
bool valid_max = hmac::is_totp_token_valid(token_max, key.data(), key.size(), early_timestamp, period, digits, hmac::TypeHash::SHA1);
assert(!valid_max);
int token = hmac::get_hotp_code(key.data(), key.size(), max_counter, digits, hmac::TypeHash::SHA1);
EXPECT_FALSE(hmac::is_totp_token_valid(token, key.data(), key.size(), early_timestamp, period, digits, hmac::TypeHash::SHA1));
}

// At maximum timestamp, ensure overflow does not validate counter 0 token
TEST(TotpBoundaryTest, MaxTimestampDoesNotValidateCounterZero) {
std::string key = "12345678901234567890";
int digits = 6;
uint64_t max_timestamp = std::numeric_limits<uint64_t>::max();
int token_zero = hmac::get_hotp_code(key.data(), key.size(), 0, digits, hmac::TypeHash::SHA1);
bool valid_zero_at_max = hmac::is_totp_token_valid(token_zero, key.data(), key.size(), max_timestamp, 1, digits, hmac::TypeHash::SHA1);
assert(!valid_zero_at_max);

// Token for max counter should still be valid at that timestamp
int token_max_ts = hmac::get_hotp_code(key.data(), key.size(), max_counter, digits, hmac::TypeHash::SHA1);
bool valid_max_ts = hmac::is_totp_token_valid(token_max_ts, key.data(), key.size(), max_timestamp, 1, digits, hmac::TypeHash::SHA1);
assert(valid_max_ts);
int token = hmac::get_hotp_code(key.data(), key.size(), 0, digits, hmac::TypeHash::SHA1);
EXPECT_FALSE(hmac::is_totp_token_valid(token, key.data(), key.size(), max_timestamp, 1, digits, hmac::TypeHash::SHA1));
}

std::cout << "TOTP tests passed" << std::endl;
return 0;
TEST(TotpBoundaryTest, MaxTimestampValidatesMaxCounter) {
std::string key = "12345678901234567890";
int digits = 6;
uint64_t max_timestamp = std::numeric_limits<uint64_t>::max();
uint64_t max_counter = std::numeric_limits<uint64_t>::max();
int token = hmac::get_hotp_code(key.data(), key.size(), max_counter, digits, hmac::TypeHash::SHA1);
EXPECT_TRUE(hmac::is_totp_token_valid(token, key.data(), key.size(), max_timestamp, 1, digits, hmac::TypeHash::SHA1));
}
Loading