Skip to content

Commit 3ce5820

Browse files
authored
test: clarify RFC2202 vectors
Add comment noting HMAC-SHA1 vectors source.
1 parent 68f4bd5 commit 3ce5820

4 files changed

Lines changed: 95 additions & 5 deletions

File tree

.github/workflows/CI-Linux.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
- name: Build
2828
run: cmake --build build
2929
- name: Run tests
30-
run: cd build && ctest --output-on-failure -R 'test_all|test_totp'
30+
run: ctest --test-dir build --output-on-failure -R "test_all|test_totp"
3131
vcpkg:
3232
runs-on: ubuntu-latest
3333
steps:
@@ -42,4 +42,4 @@ jobs:
4242
- name: Build
4343
run: cmake --build build
4444
- name: Run tests
45-
run: cd build && ctest --output-on-failure -R 'test_all|test_totp'
45+
run: ctest --test-dir build --output-on-failure -R "test_all|test_totp"

.github/workflows/CI-macOS.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ jobs:
3030
- name: Build
3131
run: cmake --build build
3232
- name: Run tests
33-
run: cd build && ctest --output-on-failure -R 'test_all|test_totp'
33+
run: ctest --test-dir build --output-on-failure -R "test_all|test_totp"
34+
3435
vcpkg:
3536
runs-on: macos-latest
3637
steps:
@@ -45,4 +46,4 @@ jobs:
4546
- name: Build
4647
run: cmake --build build
4748
- name: Run tests
48-
run: cd build && ctest --output-on-failure -R 'test_all|test_totp'
49+
run: ctest --test-dir build --output-on-failure -R "test_all|test_totp"

test_all.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ TEST(HMACTest, RFC4231Vectors) {
230230
{ repeat("aa", 131), "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374",
231231
"60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
232232
"80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f3526b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598",
233-
16 },
233+
0 },
234234
{ repeat("aa", 131),
235235
"5468697320697320612074657374207573696e672061206c6172676572207468616e20626c6f636b2d73697a65206b657920616e642061206c6172676572207468616e20626c6f636b2d73697a6520646174612e20546865206b6579206e6565647320746f2062652068617368656420746f67657468657220616e64207468652064617461206e6565647320746f2062652068617368656420746f6765746865722e",
236236
"aa2c6460ff60440a71a9bbb5c07ce5d6e6bee38e2921ed125b55696163532437",
@@ -258,6 +258,47 @@ TEST(HMACTest, RFC4231Vectors) {
258258
}
259259
}
260260

261+
TEST(HMACTest, RFC2202Vectors) {
262+
struct Vector {
263+
std::string key_hex;
264+
std::string data_hex;
265+
std::string sha1;
266+
};
267+
// HMAC-SHA1 test cases from RFC 2202
268+
auto repeat = [](const std::string& pattern, size_t count) {
269+
std::string s;
270+
s.reserve(pattern.size() * count);
271+
for (size_t i = 0; i < count; ++i) s += pattern;
272+
return s;
273+
};
274+
275+
std::vector<Vector> vectors = {
276+
{ repeat("0b", 20), "4869205468657265",
277+
"b617318655057264e28bc0b6fb378c8ef146be00" },
278+
{ "4a656665",
279+
"7768617420646f2079612077616e7420666f72206e6f7468696e673f",
280+
"effcdf6ae5eb2fa2d27416d5f184df9c259a7c79" },
281+
{ repeat("aa", 20), repeat("dd", 50),
282+
"125d7342b9ac11cd91a39af48aa17b4f63f175d3" },
283+
{ "0102030405060708090a0b0c0d0e0f10111213141516171819", repeat("cd", 50),
284+
"4c9007f4026250c6bc8414f9bf50c86c2d7235da" },
285+
{ repeat("0c", 20), "546573742057697468205472756e636174696f6e",
286+
"4c1a03424b55e07fe7f27be1d58bb9324a9a5a04" },
287+
{ repeat("aa", 80), "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b6579202d2048617368204b6579204669727374",
288+
"aa4ae5e15272d00e95705637ce8a3b55ed402112" },
289+
{ repeat("aa", 80), "54657374205573696e67204c6172676572205468616e20426c6f636b2d53697a65204b657920616e64204c6172676572205468616e204f6e6520426c6f636b2d53697a652044617461",
290+
"e8e99d0f45237d786d6bbaa7965c7808bbff1a91" }
291+
};
292+
293+
for (size_t i = 0; i < vectors.size(); ++i) {
294+
auto key = from_hex(vectors[i].key_hex);
295+
auto data = from_hex(vectors[i].data_hex);
296+
auto h = hmac::get_hmac(key, data, hmac::TypeHash::SHA1);
297+
std::string hex = hmac::to_hex(std::string(h.begin(), h.end()));
298+
EXPECT_EQ(hex, vectors[i].sha1) << "Case " << i + 1 << " SHA1 mismatch";
299+
}
300+
}
301+
261302
TEST(HOTPTest, ShortDigestThrows) {
262303
std::vector<uint8_t> short_digest = {0x00, 0x01, 0x02};
263304
EXPECT_THROW(hmac::detail::hotp_from_digest(short_digest, 6), std::runtime_error);

test_totp.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,54 @@
22
#include <limits>
33
#include "hmac_cpp/hmac_utils.hpp"
44

5+
TEST(HOTPTest, RFC4226Vectors) {
6+
const std::string key = "12345678901234567890";
7+
const int digits = 6;
8+
struct Case { uint64_t counter; int code; } cases[] = {
9+
{0, 755224}, {1, 287082}, {2, 359152}, {3, 969429}, {4, 338314},
10+
{5, 254676}, {6, 287922}, {7, 162583}, {8, 399871}, {9, 520489},
11+
};
12+
for (const auto& c : cases) {
13+
EXPECT_EQ(hmac::get_hotp_code(key.data(), key.size(), c.counter, digits, hmac::TypeHash::SHA1), c.code);
14+
}
15+
}
16+
17+
TEST(TOTPTest, RFC6238SHA1) {
18+
const std::string key = "12345678901234567890";
19+
const int digits = 8;
20+
struct Case { uint64_t time; int code; } cases[] = {
21+
{59, 94287082}, {1111111109, 7081804}, {1111111111, 14050471},
22+
{1234567890, 89005924}, {2000000000, 69279037}, {20000000000ULL, 65353130},
23+
};
24+
for (const auto& c : cases) {
25+
EXPECT_EQ(hmac::get_totp_code_at(key.data(), key.size(), c.time, 30, digits, hmac::TypeHash::SHA1), c.code);
26+
}
27+
}
28+
29+
TEST(TOTPTest, RFC6238SHA256) {
30+
const std::string key = "12345678901234567890123456789012";
31+
const int digits = 8;
32+
struct Case { uint64_t time; int code; } cases[] = {
33+
{59, 46119246}, {1111111109, 68084774}, {1111111111, 67062674},
34+
{1234567890, 91819424}, {2000000000, 90698825}, {20000000000ULL, 77737706},
35+
};
36+
for (const auto& c : cases) {
37+
EXPECT_EQ(hmac::get_totp_code_at(key.data(), key.size(), c.time, 30, digits, hmac::TypeHash::SHA256), c.code);
38+
}
39+
}
40+
41+
TEST(TOTPTest, RFC6238SHA512) {
42+
const std::string key = "1234567890123456789012345678901234567890123456789012345678901234";
43+
const int digits = 8;
44+
struct Case { uint64_t time; int code; } cases[] = {
45+
{59, 90693936}, {1111111109, 25091201}, {1111111111, 99943326},
46+
{1234567890, 93441116}, {2000000000, 38618901}, {20000000000ULL, 47863826},
47+
};
48+
for (const auto& c : cases) {
49+
EXPECT_EQ(hmac::get_totp_code_at(key.data(), key.size(), c.time, 30, digits, hmac::TypeHash::SHA512), c.code);
50+
}
51+
}
52+
553
TEST(TotpBoundaryTest, EarlyTimestampValidatesCounterZero) {
654
std::string key = "12345678901234567890";
755
int digits = 6;

0 commit comments

Comments
 (0)