diff --git a/hmac_utils.cpp b/hmac_utils.cpp index 46d67a3..820953b 100644 --- a/hmac_utils.cpp +++ b/hmac_utils.cpp @@ -8,7 +8,10 @@ namespace hmac { if (interval_sec <= 0) { throw std::invalid_argument("interval_sec must be positive"); } - auto now = std::time(nullptr); + std::time_t now = std::time(nullptr); + if (now == static_cast(-1)) { + throw std::runtime_error("std::time failed"); + } std::time_t rounded = (now / interval_sec) * interval_sec; return get_hmac(key, std::to_string(rounded), hash_type); } @@ -17,7 +20,10 @@ namespace hmac { if (interval_sec <= 0) { throw std::invalid_argument("interval_sec must be positive"); } - auto now = std::time(nullptr); + std::time_t now = std::time(nullptr); + if (now == static_cast(-1)) { + throw std::runtime_error("std::time failed"); + } std::time_t rounded = (now / interval_sec) * interval_sec; if (token == get_hmac(key, std::to_string(rounded), hash_type)) return true; if (token == get_hmac(key, std::to_string(rounded - interval_sec), hash_type)) return true; @@ -29,7 +35,10 @@ namespace hmac { if (interval_sec <= 0) { throw std::invalid_argument("interval_sec must be positive"); } - auto now = std::time(nullptr); + std::time_t now = std::time(nullptr); + if (now == static_cast(-1)) { + throw std::runtime_error("std::time failed"); + } std::time_t rounded = (now / interval_sec) * interval_sec; std::string payload = std::to_string(rounded) + "|" + fingerprint; return get_hmac(key, payload, hash_type); @@ -39,7 +48,10 @@ namespace hmac { if (interval_sec <= 0) { throw std::invalid_argument("interval_sec must be positive"); } - auto now = std::time(nullptr); + std::time_t now = std::time(nullptr); + if (now == static_cast(-1)) { + throw std::runtime_error("std::time failed"); + } std::time_t rounded = (now / interval_sec) * interval_sec; std::string prefix = "|" + fingerprint; std::string payload = std::to_string(rounded) + prefix; @@ -112,7 +124,11 @@ namespace hmac { if (digits < 1 || digits > 9) { throw std::invalid_argument("TOTP: digits must be in range [1, 9]"); } - uint64_t timestamp = static_cast(std::time(nullptr)); + std::time_t now = std::time(nullptr); + if (now == static_cast(-1)) { + throw std::runtime_error("std::time failed"); + } + uint64_t timestamp = static_cast(now); return get_totp_code_at(key_ptr, key_len, timestamp, period, digits, hash_type); } @@ -154,7 +170,11 @@ namespace hmac { if (digits < 1 || digits > 9) { throw std::invalid_argument("TOTP: digits must be in range [1, 9]"); } - uint64_t timestamp = static_cast(std::time(nullptr)); + std::time_t now = std::time(nullptr); + if (now == static_cast(-1)) { + throw std::runtime_error("std::time failed"); + } + uint64_t timestamp = static_cast(now); uint64_t counter = timestamp / period; if (token == get_hotp_code(key_ptr, key_len, counter, digits, hash_type)) return true; if (token == get_hotp_code(key_ptr, key_len, counter + 1, digits, hash_type)) return true; diff --git a/hmac_utils.hpp b/hmac_utils.hpp index 446c837..5d1d7d0 100644 --- a/hmac_utils.hpp +++ b/hmac_utils.hpp @@ -12,6 +12,7 @@ namespace hmac { /// \param interval_sec Interval in seconds that defines token rotation. Must be positive. Default is 60 seconds /// \param hash_type Hash function to use (SHA1, SHA256, SHA512). Default is SHA256 /// \return Hex-encoded HMAC-SHA256 of the rounded time value + /// \throws std::runtime_error if the system time cannot be retrieved std::string generate_time_token(const std::string &key, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256); /// \brief Validates a time-based HMAC-SHA256 token with ±1 interval tolerance @@ -20,6 +21,7 @@ namespace hmac { /// \param interval_sec Interval in seconds that defines token rotation. Must be positive. Default is 60 seconds /// \param hash_type Hash function to use (SHA1, SHA256, SHA512). Default is SHA256 /// \return true if the token is valid within the ±1 interval range; false otherwise + /// \throws std::runtime_error if the system time cannot be retrieved bool is_token_valid(const std::string &token, const std::string &key, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256); /// \brief Generates a time-based HMAC-SHA256 token with fingerprint binding @@ -28,6 +30,7 @@ namespace hmac { /// \param interval_sec Interval in seconds that defines token rotation. Must be positive. Default is 60 seconds /// \param hash_type Hash function to use (SHA1, SHA256, SHA512). Default is SHA256 /// \return Hex-encoded HMAC-SHA256 of the concatenated timestamp and fingerprint + /// \throws std::runtime_error if the system time cannot be retrieved std::string generate_time_token(const std::string &key, const std::string &fingerprint, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256); /// \brief Validates a fingerprint-bound HMAC-SHA256 token with ±1 interval tolerance @@ -37,6 +40,7 @@ namespace hmac { /// \param interval_sec Interval in seconds that defines token rotation. Must be positive. Default is 60 seconds /// \param hash_type Hash function to use (SHA1, SHA256, SHA512). Default is SHA256 /// \return true if the token is valid within the ±1 interval range; false otherwise + /// \throws std::runtime_error if the system time cannot be retrieved bool is_token_valid(const std::string &token, const std::string &key, const std::string &fingerprint, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256); /// \brief Computes HOTP code based on HMAC as defined in RFC 4226 @@ -136,6 +140,7 @@ namespace hmac { /// \param hash_type Hash function to use (default: SHA1). /// \return TOTP code as an integer. /// \throws std::invalid_argument if period <= 0 or digits not in [1,9]. + /// \throws std::runtime_error if the system time cannot be retrieved. int get_totp_code( const void* key_ptr, size_t key_len, @@ -151,6 +156,7 @@ namespace hmac { /// \param hash_type Hash function to use (default: SHA1) /// \return TOTP code as an integer /// \throws std::invalid_argument if period <= 0 or digits not in [1,9] + /// \throws std::runtime_error if the system time cannot be retrieved template inline int get_totp_code(const std::vector& key, int period = 30, int digits = 6, TypeHash hash_type = TypeHash::SHA1) { return get_totp_code(key.data(), key.size(), period, digits, hash_type); @@ -163,6 +169,7 @@ namespace hmac { /// \param hash_type Hash function to use (default: SHA1) /// \return TOTP code as an integer /// \throws std::invalid_argument if period <= 0 or digits not in [1,9] + /// \throws std::runtime_error if the system time cannot be retrieved inline int get_totp_code(const std::string& key, int period = 30, int digits = 6, TypeHash hash_type = TypeHash::SHA1) { return get_totp_code(key.data(), key.size(), period, digits, hash_type); } @@ -237,6 +244,7 @@ namespace hmac { /// \param hash_type Hash algorithm to use (default: SHA1) /// \return true if the token is valid within [-1, 0, +1] time step range; false otherwise /// \throws std::invalid_argument if period <= 0 or digits not in [1,9] + /// \throws std::runtime_error if the system time cannot be retrieved bool is_totp_token_valid( int token, const void* key_ptr, @@ -254,6 +262,7 @@ namespace hmac { /// \param hash_type Hash function to use (default: SHA1) /// \return true if the token is valid within [-1, 0, +1] time step range; false otherwise /// \throws std::invalid_argument if period <= 0 or digits not in [1,9] + /// \throws std::runtime_error if the system time cannot be retrieved template inline bool is_totp_token_valid( int token, @@ -274,6 +283,7 @@ namespace hmac { /// \param hash_type Hash function to use (default: SHA1) /// \return true if the token is valid within [-1, 0, +1] time step range; false otherwise /// \throws std::invalid_argument if period <= 0 or digits not in [1,9] + /// \throws std::runtime_error if the system time cannot be retrieved inline bool is_totp_token_valid( int token, const std::string& key,