From 2fd752f311c9cdbad300d59877bb3987ee90e502 Mon Sep 17 00:00:00 2001 From: Aster Seker Date: Sat, 6 Sep 2025 01:39:43 +0300 Subject: [PATCH] docs(readme): document pbkdf2 usage --- README-RU.md | 40 ++++++++++++++++++++------- README.md | 78 ++++++++++++++++++---------------------------------- 2 files changed, 57 insertions(+), 61 deletions(-) diff --git a/README-RU.md b/README-RU.md index 3479a26..241ddfb 100644 --- a/README-RU.md +++ b/README-RU.md @@ -153,22 +153,42 @@ std::vector get_hmac( Возвращает: Бинарный HMAC в виде `std::vector` -### PBKDF2 (RFC 8018) +### PBKDF2 + +PBKDF2 преобразует пароль пользователя в криптографический ключ. +Используется для шифрования и хранения хешей паролей. ```cpp #include - -std::string password = "password"; -std::vector salt(16, 0x01); -std::vector 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 токены diff --git a/README.md b/README.md index 0457e09..ea4395f 100644 --- a/README.md +++ b/README.md @@ -182,55 +182,45 @@ Parameters: Returns: Binary digest as `std::vector` -### 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 - -std::string password = "password"; -std::vector salt(16, 0x01); // at least 16 bytes -std::vector 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 -#include +| 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 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 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) @@ -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)