Skip to content

Commit e8a54e7

Browse files
committed
feat(utils): add constant_time_equal alias
Expose constant_time_equal as alias and document MAC verification.
1 parent e685fd3 commit e8a54e7

3 files changed

Lines changed: 30 additions & 6 deletions

File tree

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -265,21 +265,25 @@ The example is in `example.cpp` and is built automatically when `BUILD_EXAMPLE=O
265265
```cpp
266266
#include <iostream>
267267
#include <hmac_cpp/hmac.hpp>
268+
#include <hmac_cpp/hmac_utils.hpp>
268269

269270
int main() {
270271
std::string input = "grape";
271272
std::string key = "12345";
272273

273-
std::string hmac_sha256 = hmac::get_hmac(key, input, hmac::TypeHash::SHA256);
274-
std::cout << "HMAC-SHA256: " << hmac_sha256 << std::endl;
275-
276-
std::string hmac_sha512 = hmac::get_hmac(key, input, hmac::TypeHash::SHA512);
277-
std::cout << "HMAC-SHA512: " << hmac_sha512 << std::endl;
274+
std::string mac = hmac::get_hmac(key, input, hmac::TypeHash::SHA256);
275+
if (hmac::constant_time_equal(mac,
276+
"7632ac2e8ddedaf4b3e7ab195fefd17571c37c970e02e169195a158ef59e53ca")) {
277+
std::cout << "MAC verified\n";
278+
}
278279

279280
return 0;
280281
}
281282
```
282283

284+
**Note:** avoid checking input lengths before calling `constant_time_equal`.
285+
Early length comparisons can leak information through timing side channels.
286+
283287
## 📚 Resources
284288

285289
* Original [SHA256 implementation](http://www.zedwood.com/article/cpp-sha256-function)

example.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ int main() {
3939
print_section("HMAC-SHA256");
4040
std::string hmac_sha256 = hmac::get_hmac(key, input, hmac::TypeHash::SHA256, true);
4141
std::cout << "HMAC('" << key << "', '" << input << "', SHA256) = " << hmac_sha256 << std::endl;
42-
std::cout << "Expected: 7632ac2e8ddedaf4b3e7ab195fefd17571c37c970e02e169195a158ef59e53ca\n\n";
42+
std::string expected_hmac_sha256 =
43+
"7632ac2e8ddedaf4b3e7ab195fefd17571c37c970e02e169195a158ef59e53ca";
44+
bool mac_valid = hmac::constant_time_equal(hmac_sha256, expected_hmac_sha256);
45+
std::cout << "MAC valid? = " << (mac_valid ? "YES" : "NO") << "\n\n";
4346

4447
// HMAC-SHA512
4548
print_section("HMAC-SHA512");

include/hmac_cpp/hmac_utils.hpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,23 @@ namespace hmac_cpp {
2727
reinterpret_cast<const uint8_t*>(b.data()), b.size());
2828
}
2929

30+
/// \brief Alias for constant_time_equals.
31+
/// Avoids early length checks to mitigate timing attacks.
32+
inline bool constant_time_equal(const uint8_t* a, size_t a_len,
33+
const uint8_t* b, size_t b_len) {
34+
return constant_time_equals(a, a_len, b, b_len);
35+
}
36+
37+
inline bool constant_time_equal(const std::vector<uint8_t>& a,
38+
const std::vector<uint8_t>& b) {
39+
return constant_time_equal(a.data(), a.size(), b.data(), b.size());
40+
}
41+
42+
inline bool constant_time_equal(const std::string& a, const std::string& b) {
43+
return constant_time_equal(reinterpret_cast<const uint8_t*>(a.data()), a.size(),
44+
reinterpret_cast<const uint8_t*>(b.data()), b.size());
45+
}
46+
3047
/// \brief Hash choices for PBKDF2
3148
enum class Pbkdf2Hash { Sha1, Sha256, Sha512 };
3249

0 commit comments

Comments
 (0)