From 49ecf4bfa76db287fd3ba8be404643e9710f190c Mon Sep 17 00:00:00 2001 From: Aster Seker Date: Sat, 6 Sep 2025 02:54:45 +0300 Subject: [PATCH] test: clarify RFC2202 vectors Add comment noting HMAC-SHA1 vectors source. --- .github/workflows/CI-Linux.yml | 4 +-- .github/workflows/CI-macOS.yml | 4 +-- test_all.cpp | 47 ++++++++++++++++++++++++++++++--- test_totp.cpp | 48 ++++++++++++++++++++++++++++++++++ 4 files changed, 96 insertions(+), 7 deletions(-) diff --git a/.github/workflows/CI-Linux.yml b/.github/workflows/CI-Linux.yml index 728e5e7..a45f4f7 100644 --- a/.github/workflows/CI-Linux.yml +++ b/.github/workflows/CI-Linux.yml @@ -27,7 +27,7 @@ jobs: - name: Build run: cmake --build build - name: Run tests - run: cd build && ctest --output-on-failure + run: ctest --test-dir build --output-on-failure vcpkg: runs-on: ubuntu-latest steps: @@ -42,4 +42,4 @@ jobs: - name: Build run: cmake --build build - name: Run tests - run: cd build && ctest --output-on-failure + run: ctest --test-dir build --output-on-failure diff --git a/.github/workflows/CI-macOS.yml b/.github/workflows/CI-macOS.yml index ae1f198..435cf31 100644 --- a/.github/workflows/CI-macOS.yml +++ b/.github/workflows/CI-macOS.yml @@ -30,7 +30,7 @@ jobs: - name: Build run: cmake --build build - name: Run tests - run: cd build && ctest --output-on-failure + run: ctest --test-dir build --output-on-failure vcpkg: runs-on: macos-latest steps: @@ -45,4 +45,4 @@ jobs: - name: Build run: cmake --build build - name: Run tests - run: cd build && ctest --output-on-failure + run: ctest --test-dir build --output-on-failure diff --git a/test_all.cpp b/test_all.cpp index 65543d6..50b13e3 100644 --- a/test_all.cpp +++ b/test_all.cpp @@ -192,9 +192,9 @@ TEST(HMACTest, RFC4231Vectors) { "415fad6271580a531d4179bc891d87a6", 16 }, { repeat("aa", 131), "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374", - "60e431591ee0b67f0d8a26aacbf5b77f", - "80b24263c7c1a3ebb71493c1dd7be8b4", - 16 }, + "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54", + "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598", + 0 }, { repeat("aa", 131), "5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f2062652068617368656420746f67657468657220616e64207468652064617461206e6565647320746f2062652068617368656420746f6765746865722e", "aa2c6460ff60440a71a9bbb5c07ce5d6e6bee38e2921ed125b55696163532437", @@ -218,6 +218,47 @@ TEST(HMACTest, RFC4231Vectors) { } } +TEST(HMACTest, RFC2202Vectors) { + struct Vector { + std::string key_hex; + std::string data_hex; + std::string sha1; + }; + // HMAC-SHA1 test cases from RFC 2202 + auto repeat = [](const std::string& pattern, size_t count) { + std::string s; + s.reserve(pattern.size() * count); + for (size_t i = 0; i < count; ++i) s += pattern; + return s; + }; + + std::vector vectors = { + { repeat("0b", 20), "4869205468657265", + "b617318655057264e28bc0b6fb378c8ef146be00" }, + { "4a656665", + "7768617420646f2079612077616e7420666f72206e6f7468696e673f", + "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79" }, + { repeat("aa", 20), repeat("dd", 50), + "125d7342b9ac11cd91a39af48aa17b4f63f175d3" }, + { "0102030405060708090a0b0c0d0e0f10111213141516171819", repeat("cd", 50), + "4c9007f4026250c6bc8414f9bf50c86c2d7235da" }, + { repeat("0c", 20), "546573742057697468205472756e636174696f6e", + "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04" }, + { repeat("aa", 80), "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374", + "aa4ae5e15272d00e95705637ce8a3b55ed402112" }, + { repeat("aa", 80), "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d53697a652044617461", + "e8e99d0f45237d786d6bbaa7965c7808bbff1a91" } + }; + + for (size_t i = 0; i < vectors.size(); ++i) { + auto key = from_hex(vectors[i].key_hex); + auto data = from_hex(vectors[i].data_hex); + auto h = hmac::get_hmac(key, data, hmac::TypeHash::SHA1); + std::string hex = hmac::to_hex(std::string(h.begin(), h.end())); + EXPECT_EQ(hex, vectors[i].sha1) << "Case " << i + 1 << " SHA1 mismatch"; + } +} + TEST(HOTPTest, ShortDigestThrows) { std::vector short_digest = {0x00, 0x01, 0x02}; EXPECT_THROW(hmac::detail::hotp_from_digest(short_digest, 6), std::runtime_error); diff --git a/test_totp.cpp b/test_totp.cpp index 5cdf12d..e9b021a 100644 --- a/test_totp.cpp +++ b/test_totp.cpp @@ -2,6 +2,54 @@ #include #include "hmac_cpp/hmac_utils.hpp" +TEST(HOTPTest, RFC4226Vectors) { + const std::string key = "12345678901234567890"; + const int digits = 6; + struct Case { uint64_t counter; int code; } cases[] = { + {0, 755224}, {1, 287082}, {2, 359152}, {3, 969429}, {4, 338314}, + {5, 254676}, {6, 287922}, {7, 162583}, {8, 399871}, {9, 520489}, + }; + for (const auto& c : cases) { + EXPECT_EQ(hmac::get_hotp_code(key.data(), key.size(), c.counter, digits, hmac::TypeHash::SHA1), c.code); + } +} + +TEST(TOTPTest, RFC6238SHA1) { + const std::string key = "12345678901234567890"; + const int digits = 8; + struct Case { uint64_t time; int code; } cases[] = { + {59, 94287082}, {1111111109, 7081804}, {1111111111, 14050471}, + {1234567890, 89005924}, {2000000000, 69279037}, {20000000000ULL, 65353130}, + }; + for (const auto& c : cases) { + EXPECT_EQ(hmac::get_totp_code_at(key.data(), key.size(), c.time, 30, digits, hmac::TypeHash::SHA1), c.code); + } +} + +TEST(TOTPTest, RFC6238SHA256) { + const std::string key = "12345678901234567890123456789012"; + const int digits = 8; + struct Case { uint64_t time; int code; } cases[] = { + {59, 46119246}, {1111111109, 68084774}, {1111111111, 67062674}, + {1234567890, 91819424}, {2000000000, 90698825}, {20000000000ULL, 77737706}, + }; + for (const auto& c : cases) { + EXPECT_EQ(hmac::get_totp_code_at(key.data(), key.size(), c.time, 30, digits, hmac::TypeHash::SHA256), c.code); + } +} + +TEST(TOTPTest, RFC6238SHA512) { + const std::string key = "1234567890123456789012345678901234567890123456789012345678901234"; + const int digits = 8; + struct Case { uint64_t time; int code; } cases[] = { + {59, 90693936}, {1111111109, 25091201}, {1111111111, 99943326}, + {1234567890, 93441116}, {2000000000, 38618901}, {20000000000ULL, 47863826}, + }; + for (const auto& c : cases) { + EXPECT_EQ(hmac::get_totp_code_at(key.data(), key.size(), c.time, 30, digits, hmac::TypeHash::SHA512), c.code); + } +} + TEST(TotpBoundaryTest, EarlyTimestampValidatesCounterZero) { std::string key = "12345678901234567890"; int digits = 6;