Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 18 additions & 5 deletions README-RU.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ auto sig = hmac::get_hmac(key, payload, hmac::TypeHash::SHA256);
secure_zero(key); // при необходимости: очистить после использования
```

Чтобы сравнить два токена напрямую, используйте
`hmac::constant_time_equal` для защиты от атак по времени:

```cpp
bool same = hmac::constant_time_equal(expected_token, user_token); // длины публичны
```

### HMAC (сырые бинарные данные)

```cpp
Expand Down Expand Up @@ -269,21 +276,27 @@ try {
```cpp
#include <iostream>
#include <hmac_cpp/hmac.hpp>
#include <hmac_cpp/hmac_utils.hpp>

int main() {
std::string input = "grape";
std::string key = "12345";

std::string hmac_sha256 = hmac::get_hmac(key, input, hmac::TypeHash::SHA256);
std::cout << "HMAC-SHA256: " << hmac_sha256 << std::endl;

std::string hmac_sha512 = hmac::get_hmac(key, input, hmac::TypeHash::SHA512);
std::cout << "HMAC-SHA512: " << hmac_sha512 << std::endl;
std::string mac = hmac::get_hmac(key, input, hmac::TypeHash::SHA256);
if (hmac::constant_time_equal(mac,
"7632ac2e8ddedaf4b3e7ab195fefd17571c37c970e02e169195a158ef59e53ca")) {
std::cout << "MAC проверен\n";
}

return 0;
}
```

**Примечание:** `constant_time_equal` считает длину входных данных публичной и
время работы зависит от максимальной длины. Не проверяйте длины отдельно —
ранние проверки могут выдать информацию через побочные каналы времени
выполнения.

## 📚 Полезные ссылки

* Исходный код [SHA256](http://www.zedwood.com/article/cpp-sha256-function)
Expand Down
12 changes: 10 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,13 @@ std::vector<uint8_t> sig =
secure_zero(key); // optional: wipe after use
```

To compare two tokens directly, use `hmac::constant_time_equal` for a
timing-safe check:

```cpp
bool same = hmac::constant_time_equal(expected_token, user_token); // lengths are public
```

### HMAC (binary data: raw buffer)

```cpp
Expand Down Expand Up @@ -326,8 +333,9 @@ int main() {
}
```

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

## 📚 Resources

Expand Down
27 changes: 13 additions & 14 deletions include/hmac_cpp/hmac_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ namespace hmac_cpp {
HMAC_CPP_API bool constant_time_equals(const uint8_t* a, size_t a_len,
const uint8_t* b, size_t b_len);

/// \brief Alias for \c constant_time_equals.
/// \param a Pointer to first array.
/// \param a_len Length of the first array.
/// \param b Pointer to second array.
/// \param b_len Length of the second array.
/// \return true if both arrays are equal.
/// \note Avoids early length checks; input lengths are treated as public
/// and may influence timing.
HMAC_CPP_API bool constant_time_equal(const uint8_t* a, size_t a_len,
const uint8_t* b, size_t b_len);

/// \brief Compare vectors in constant time.
/// \param a First vector.
/// \param b Second vector.
Expand All @@ -42,19 +53,7 @@ namespace hmac_cpp {
reinterpret_cast<const uint8_t*>(b.data()), b.size());
}

/// \brief Alias for constant_time_equals.
/// \param a Pointer to first array.
/// \param a_len Length of the first array.
/// \param b Pointer to second array.
/// \param b_len Length of the second array.
/// \return true if both arrays are equal.
/// \note Avoids early length checks to mitigate timing attacks.
inline bool constant_time_equal(const uint8_t* a, size_t a_len,
const uint8_t* b, size_t b_len) {
return constant_time_equals(a, a_len, b, b_len);
}

/// \brief Alias for constant_time_equals on vectors.
/// \brief Alias for \c constant_time_equal on vectors.
/// \param a First vector.
/// \param b Second vector.
/// \return true if both vectors are equal.
Expand All @@ -63,7 +62,7 @@ namespace hmac_cpp {
return constant_time_equal(a.data(), a.size(), b.data(), b.size());
}

/// \brief Alias for constant_time_equals on strings.
/// \brief Alias for \c constant_time_equal on strings.
/// \param a First string.
/// \param b Second string.
/// \return true if both strings are equal.
Expand Down
5 changes: 5 additions & 0 deletions src/hmac_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ namespace hmac_cpp {
return diff == 0;
}

bool constant_time_equal(const uint8_t* a, size_t a_len,
const uint8_t* b, size_t b_len) {
return constant_time_equals(a, a_len, b, b_len);
}

static TypeHash to_type_hash(Pbkdf2Hash prf) {
switch (prf) {
case Pbkdf2Hash::Sha1: return TypeHash::SHA1;
Expand Down
Loading