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
40 changes: 30 additions & 10 deletions README-RU.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,22 +153,42 @@ std::vector<uint8_t> get_hmac(

Возвращает: Бинарный HMAC в виде `std::vector<uint8_t>`

### PBKDF2 (RFC 8018)
### PBKDF2

PBKDF2 преобразует пароль пользователя в криптографический ключ.
Используется для шифрования и хранения хешей паролей.

```cpp
#include <hmac_cpp/hmac_utils.hpp>

std::string password = "password";
std::vector<uint8_t> salt(16, 0x01);
std::vector<uint8_t> dk = hmac::pbkdf2(password, salt, 1000, 32);
auto salt = hmac::random_bytes(16);
auto key = hmac::pbkdf2_hmac_sha256(password, salt, iters, 32);
```

Параметры:
Рекомендации:

- **Соль:** случайные 16–32 байта.
- **Итерации:** подбирайте число так, чтобы вычисление занимало ~100–250 мс на целевой машине.
- **Длина ключа:** 32 байта.
- **Алгоритм:** HMAC-SHA-256.

Параметры и шифротекст можно сериализовать, например, так:
`magic|salt|iters|iv|ct|tag`.

См. `example_pbkdf2.cpp` для полноценного примера.

#### Рекомендуемые параметры

| Цель | Итерации | Длина ключа | PRF |
|--------|---------:|------------:|-------------|
| Desktop| 600000 | 32 байта | HMAC-SHA256 |
| Laptop | 300000 | 32 байта | HMAC-SHA256 |
| Mobile | 150000 | 32 байта | HMAC-SHA256 |

#### Примечания по безопасности

- `password`, `salt` — байтовые строки; `salt` должна быть уникальной и не короче 16 байт
- `iterations` — число итераций (≥1), подбирается по [рекомендациям OWASP](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html)
- `dk_len` — длина ключа в байтах, не более `(2^32−1) * hLen`
- `prf` — выбор хеша (`Sha1`, `Sha256` по умолчанию, `Sha512`)
- PBKDF2 зависит от CPU и уязвим для атак с использованием GPU/ASIC, поэтому выбирайте высокое число итераций или более сильные KDF.
- Каждому паролю нужна уникальная случайная соль достаточной длины.
- Соль, итерации и алгоритм не являются секретом — храните их вместе с хешем или шифротекстом.

### 🕓 HOTP и TOTP токены

Expand Down
78 changes: 27 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,55 +182,45 @@ Parameters:

Returns: Binary digest as `std::vector<uint8_t>`

### PBKDF2 Key Derivation
### PBKDF2

PBKDF2 derives a cryptographic key from a user password. It is typically
used to unlock encrypted data or verify password hashes.

```cpp
#include <hmac_cpp/hmac_utils.hpp>

std::string password = "password";
std::vector<uint8_t> salt(16, 0x01); // at least 16 bytes
std::vector<uint8_t> dk = hmac::pbkdf2(password, salt, 1000, 32);
hmac::Pbkdf2Result stored{salt, 1000, dk};
auto verify = hmac::pbkdf2(password, stored);
bool ok = hmac::constant_time_equals(verify.key, stored.key);
auto salt = hmac::random_bytes(16);
auto key = hmac::pbkdf2_hmac_sha256(password, salt, iters, 32);
```

Parameters:

- `password`, `salt` — Raw byte arrays. `salt` must be **>=16 bytes** and unique.
- `iterations` — Number of iterations (>=1). Tune according to the
[OWASP Password Storage Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html).
- `dk_len` — Desired key length in bytes, up to `(2^32-1) * hLen` (RFC 8018).
- `prf` — Optional hash (`Sha1`, `Sha256` default, `Sha512`).

⚠️ Low iteration counts or short salts reduce security.
Recommendations:

For deployments with a server-side *pepper*, use `pbkdf2_with_pepper(password, salt, pepper, iters, dkLen)`.
The pepper is a secret key stored separately from the hashed password.
- **Salt:** 16–32 random bytes.
- **Iterations:** pick a value so derivation takes ~100–250 ms on the target
machine.
- **Derived key length:** 32 bytes.
- **Algorithm:** HMAC-SHA-256.

### PBKDF2 Security Notes
Parameters and ciphertext may be serialized as:
`magic|salt|iters|iv|ct|tag`.

- Use a random salt of **at least 16 bytes** and never reuse it.
- Choose an iteration count that takes roughly **200–500 ms** on your target hardware (~2025).
- Store `{salt, iterations}` alongside the ciphertext or hash; these values are public.
- Salts and iteration counts must be unique per password.
- Example serialization: `{magic|ver|prf|salt|iters|dkLen|…}`.
See `example_pbkdf2.cpp` for a complete example.

#### PBKDF2-HMAC-SHA256 + AES-GCM
#### Recommended Parameters

```cpp
#include <hmac_cpp/hmac_utils.hpp>
#include <aes_cpp/aes_utils.hpp>
| Target | Iterations | Derived key length | PRF |
|---------|-----------:|------------------:|-----|
| Desktop | 600000 | 32 bytes | HMAC-SHA256 |
| Laptop | 300000 | 32 bytes | HMAC-SHA256 |
| Mobile | 150000 | 32 bytes | HMAC-SHA256 |

std::string password = "correct horse battery staple";
std::vector<uint8_t> salt(16, 0x00); // 16 random bytes
auto key = hmac::pbkdf2(password, salt, 100000, 32, hmac::Pbkdf2Hash::Sha256);
#### Security Notes

std::string plaintext = "secret";
std::vector<uint8_t> aad = {'h','e','a','d','e','r'};
auto pkt = aes_cpp::utils::encrypt_gcm(plaintext, key, aad);
auto restored = aes_cpp::utils::decrypt_gcm_to_string(pkt, key, aad);
```
- PBKDF2 is CPU-bound and vulnerable to massive GPU/ASIC brute force.
Choose high iteration counts or stronger KDFs.
- Every password requires a unique, random salt of sufficient length.
- Salts, iteration counts, and algorithms are not secrets—store them
alongside the hash or ciphertext.

### HKDF (RFC 5869)

Expand Down Expand Up @@ -337,20 +327,6 @@ int main() {
**Note:** avoid checking input lengths before calling `constant_time_equal`.
Early length comparisons can leak information through timing side channels.

## PBKDF2 Recommended Parameters

| Target | Iterations | Derived key length | PRF |
|---------|-----------:|------------------:|-----|
| Desktop | 600000 | 32 bytes | HMAC-SHA256 |
| Laptop | 300000 | 32 bytes | HMAC-SHA256 |
| Mobile | 150000 | 32 bytes | HMAC-SHA256 |

## Security Notes

- PBKDF2 is CPU-bound and vulnerable to massive GPU/ASIC brute force. Choose high iteration counts or stronger KDFs.
- Every password requires a unique, random salt of sufficient length.
- Salts, iteration counts, and algorithms are not secrets—store them alongside the hash for verification.

## 📚 Resources

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