Skip to content

Commit 1a99920

Browse files
authored
feat(utils): export constant_time_equal
2 parents 4b51dfb + ed69751 commit 1a99920

4 files changed

Lines changed: 46 additions & 21 deletions

File tree

README-RU.md

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ auto sig = hmac::get_hmac(key, payload, hmac::TypeHash::SHA256);
112112
secure_zero(key); // при необходимости: очистить после использования
113113
```
114114
115+
Чтобы сравнить два токена напрямую, используйте
116+
`hmac::constant_time_equal` для защиты от атак по времени:
117+
118+
```cpp
119+
bool same = hmac::constant_time_equal(expected_token, user_token); // длины публичны
120+
```
121+
115122
### HMAC (сырые бинарные данные)
116123

117124
```cpp
@@ -285,21 +292,27 @@ try {
285292
```cpp
286293
#include <iostream>
287294
#include <hmac_cpp/hmac.hpp>
295+
#include <hmac_cpp/hmac_utils.hpp>
288296

289297
int main() {
290298
std::string input = "grape";
291299
std::string key = "12345";
292300

293-
std::string hmac_sha256 = hmac::get_hmac(key, input, hmac::TypeHash::SHA256);
294-
std::cout << "HMAC-SHA256: " << hmac_sha256 << std::endl;
295-
296-
std::string hmac_sha512 = hmac::get_hmac(key, input, hmac::TypeHash::SHA512);
297-
std::cout << "HMAC-SHA512: " << hmac_sha512 << std::endl;
301+
std::string mac = hmac::get_hmac(key, input, hmac::TypeHash::SHA256);
302+
if (hmac::constant_time_equal(mac,
303+
"7632ac2e8ddedaf4b3e7ab195fefd17571c37c970e02e169195a158ef59e53ca")) {
304+
std::cout << "MAC проверен\n";
305+
}
298306

299307
return 0;
300308
}
301309
```
302310

311+
**Примечание:** `constant_time_equal` считает длину входных данных публичной и
312+
время работы зависит от максимальной длины. Не проверяйте длины отдельно —
313+
ранние проверки могут выдать информацию через побочные каналы времени
314+
выполнения.
315+
303316
## 📚 Полезные ссылки
304317

305318
* Исходный код [SHA256](http://www.zedwood.com/article/cpp-sha256-function)

README.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,13 @@ std::vector<uint8_t> sig =
141141
secure_zero(key); // optional: wipe after use
142142
```
143143
144+
To compare two tokens directly, use `hmac::constant_time_equal` for a
145+
timing-safe check:
146+
147+
```cpp
148+
bool same = hmac::constant_time_equal(expected_token, user_token); // lengths are public
149+
```
150+
144151
### HMAC (binary data: raw buffer)
145152

146153
```cpp
@@ -344,8 +351,9 @@ int main() {
344351
}
345352
```
346353

347-
**Note:** avoid checking input lengths before calling `constant_time_equal`.
348-
Early length comparisons can leak information through timing side channels.
354+
**Note:** `constant_time_equal` treats input lengths as public and may run
355+
longer for longer inputs. Avoid checking lengths separately—early length
356+
comparisons can leak information through timing side channels.
349357

350358
## 📚 Resources
351359

include/hmac_cpp/hmac_utils.hpp

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,17 @@ namespace hmac_cpp {
2424
HMAC_CPP_API bool constant_time_equals(const uint8_t* a, size_t a_len,
2525
const uint8_t* b, size_t b_len);
2626

27+
/// \brief Alias for \c constant_time_equals.
28+
/// \param a Pointer to first array.
29+
/// \param a_len Length of the first array.
30+
/// \param b Pointer to second array.
31+
/// \param b_len Length of the second array.
32+
/// \return true if both arrays are equal.
33+
/// \note Avoids early length checks; input lengths are treated as public
34+
/// and may influence timing.
35+
HMAC_CPP_API bool constant_time_equal(const uint8_t* a, size_t a_len,
36+
const uint8_t* b, size_t b_len);
37+
2738
/// \brief Compare vectors in constant time.
2839
/// \param a First vector.
2940
/// \param b Second vector.
@@ -42,19 +53,7 @@ namespace hmac_cpp {
4253
reinterpret_cast<const uint8_t*>(b.data()), b.size());
4354
}
4455

45-
/// \brief Alias for constant_time_equals.
46-
/// \param a Pointer to first array.
47-
/// \param a_len Length of the first array.
48-
/// \param b Pointer to second array.
49-
/// \param b_len Length of the second array.
50-
/// \return true if both arrays are equal.
51-
/// \note Avoids early length checks to mitigate timing attacks.
52-
inline bool constant_time_equal(const uint8_t* a, size_t a_len,
53-
const uint8_t* b, size_t b_len) {
54-
return constant_time_equals(a, a_len, b, b_len);
55-
}
56-
57-
/// \brief Alias for constant_time_equals on vectors.
56+
/// \brief Alias for \c constant_time_equal on vectors.
5857
/// \param a First vector.
5958
/// \param b Second vector.
6059
/// \return true if both vectors are equal.
@@ -63,7 +62,7 @@ namespace hmac_cpp {
6362
return constant_time_equal(a.data(), a.size(), b.data(), b.size());
6463
}
6564

66-
/// \brief Alias for constant_time_equals on strings.
65+
/// \brief Alias for \c constant_time_equal on strings.
6766
/// \param a First string.
6867
/// \param b Second string.
6968
/// \return true if both strings are equal.

src/hmac_utils.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ namespace hmac_cpp {
2121
return diff == 0;
2222
}
2323

24+
bool constant_time_equal(const uint8_t* a, size_t a_len,
25+
const uint8_t* b, size_t b_len) {
26+
return constant_time_equals(a, a_len, b, b_len);
27+
}
28+
2429
static TypeHash to_type_hash(Pbkdf2Hash prf) {
2530
switch (prf) {
2631
case Pbkdf2Hash::Sha1: return TypeHash::SHA1;

0 commit comments

Comments
 (0)