hmac-cpp 🇷🇺 README-RU
A lightweight C++11 library for computing HMAC (SHA-1/SHA-256/SHA-512), key derivation (PBKDF2, HKDF), and OTP (HOTP, TOTP). Includes optional time-based HMAC tokens for simple stateless use-cases and MQL5 compatibility.
-
C++11 compatible
-
HMAC with SHA1, SHA256, SHA512
-
Output as binary or hex
-
PBKDF2 (RFC 8018) — password-based key derivation
-
HKDF (RFC 5869) — key extraction/expansion
-
OTP:
- HOTP (RFC 4226) — counter-based
- TOTP (RFC 6238) — time-based
-
Time-based HMAC tokens — lightweight, stateless HMAC(timestamp)-style tokens (not TOTP/HOTP)
-
MQL5 support — adapted SHA/HMAC for MetaTrader 5
-
Exported CMake package target:
hmac_cpp::hmac_cpp
CI covers Linux/Windows/macOS. Tested with GCC, Clang, and MSVC; requires C++11.
Examples, tests, and benchmarks are OFF by default. Enable via:
HMACCPP_BUILD_EXAMPLESHMACCPP_BUILD_TESTSHMACCPP_BUILD_BENCH
cmake -B build -DHMACCPP_BUILD_EXAMPLES=ON
cmake --build buildcmake --install build --prefix _installInstall layout:
_install/
├─ include/hmac_cpp/
│ ├─ hmac.hpp
│ ├─ hmac_utils.hpp
│ ├─ sha1.hpp
│ ├─ sha256.hpp
│ ├─ sha512.hpp
│ └─ secure_buffer.hpp # if included in your build
└─ lib/
└─ libhmac_cpp.a
find_package(hmac_cpp CONFIG REQUIRED)
target_link_libraries(my_app PRIVATE hmac_cpp::hmac_cpp)# adjust paths to your prefix
g++ example.cpp -std=c++11 -I_install/include -L_install/lib -lhmac_cppPredefined MinGW build scripts are available: build_*.bat.
Note on SHA-1: HMAC-SHA1 is supported for compatibility/OTP. Prefer HMAC-SHA256/512 for new designs.
std::string get_hmac(
const std::string& key,
const std::string& msg,
TypeHash type,
bool is_hex = true,
bool is_upper = false);type:hmac::TypeHash::SHA256/SHA512/SHA1- Returns hex by default. For binary output, prefer the
std::vector<uint8_t>overload.
Constant-time compare — treat lengths as public:
bool equal = (a.size() == b.size()) && hmac::constant_time_equal(a, b);(Optional) Secure handling of string keys — if you use secure_buffer:
#include <hmac_cpp/secure_buffer.hpp>
secure_buffer key(std::move(secret_string)); // zeroizes moved-from string
auto mac = hmac::get_hmac(key, payload, hmac::TypeHash::SHA256);std::vector<uint8_t> get_hmac(
const void* key_ptr, size_t key_len,
const void* msg_ptr, size_t msg_len,
TypeHash type);template<typename T>
std::vector<uint8_t> get_hmac(
const std::vector<T>& key,
const std::vector<T>& msg,
TypeHash type);
// T must be char or uint8_tDerive a key from a password.
#include <hmac_cpp/hmac_utils.hpp>
auto salt = hmac::random_bytes(16);
auto key = hmac::pbkdf2_hmac_sha256(password, salt, iters, 32); // 32 = AES-256Recommendations
- Salt: 16–32 random bytes (unique per password). Store next to ciphertext.
- Iterations: tune for ~100–250 ms on target hardware (e.g., desktop ≈ 600k, laptop ≈ 300k, mobile ≈ 150k; adjust).
- Derived key length: 32 bytes; PRF: HMAC-SHA256.
Serialization example (binary):
magic(4) | ver(1) | alg(1=PBKDF2-HS256) |
iter(4, BE) | salt_len(1) | salt | iv_len(1) | iv | ct_len(4, BE) | ct | tag(16)
See example_pbkdf2.cpp for an end-to-end example.
std::vector<uint8_t> ikm = {/* secret material */};
std::vector<uint8_t> salt(16, 0x00);
auto prk = hmac::hkdf_extract_sha256(ikm, salt);
auto okm = hmac::hkdf_expand_sha256(prk, /*info=*/{}, /*L=*/32); // L ≤ 255*HashLenUtility helpers for Base64 (standard or URL alphabet) and Base32.
#include <hmac_cpp/encoding.hpp>
std::vector<uint8_t> key = {0xff, 0xee};
std::string b64 = hmac_cpp::base64_encode(key, hmac_cpp::Base64Alphabet::Url, false);
hmac_cpp::secure_buffer<uint8_t> raw;
hmac_cpp::base64_decode(b64, raw, hmac_cpp::Base64Alphabet::Url, false);OTP per RFC 4226/6238. Secrets should be random (not passwords). If you receive Base32 (otpauth URI), decode before calling.
- HOTP — 6 digits, SHA-1 (default).
- TOTP — 30 s step, 6 digits, SHA-1 (default).
is_totp_token_validchecks ±1 step by default.
#include <hmac_cpp/hmac_utils.hpp>
std::string key = "12345678901234567890"; // raw bytes
uint64_t counter = 0;
int hotp = get_hotp_code(key, counter);
int totp = get_totp_code(key); // now()Validation example (RFC 6238 vector):
bool ok = hmac::is_totp_token_valid(94287082, key, /*time=*/59, /*step=*/30,
/*digits=*/8, hmac::TypeHash::SHA1);A simple stateless HMAC(timestamp) scheme (not TOTP/HOTP):
- Default SHA256 (also SHA1/SHA512 supported)
- Full HMAC digest as tag (hex)
- Valid within previous/current/next interval (±
interval_sec) - Optional binding to a client fingerprint (device ID, etc.)
- No replay protection within the interval — use TOTP/HOTP or server-side nonce tracking for high-risk scenarios
std::string token = hmac::generate_time_token(secret_key, /*interval=*/60);
bool valid = hmac::is_token_valid(token, secret_key, 60);
// with fingerprint
std::string t2 = hmac::generate_time_token(secret_key, fingerprint, 60);
bool v2 = hmac::is_token_valid(t2, secret_key, fingerprint, 60);Repository provides sha256.mqh, sha512.mqh, hmac.mqh, hmac_utils.mqh (MetaTrader 5).
Install: copy these files into your MT5 folder, e.g. MQL5/Include/hmac-cpp/, then:
#include <hmac-cpp/hmac.mqh>
string mac = hmac::get_hmac("key", "message", hmac::TypeHash::SHA256);| Hash function | C++ enum | MQL enum |
|---|---|---|
| SHA1 | hmac::TypeHash::SHA1 |
– (not available) |
| SHA256 | hmac::TypeHash::SHA256 |
hmac::TypeHash::SHA256 |
| SHA512 | hmac::TypeHash::SHA512 |
hmac::TypeHash::SHA512 |
Note: C++ includes use
hmac_cpp/...(underscore), MQL includes usehmac-cpp/...(dash directory name).
Enable tests and run with CTest:
cmake -B build -DHMACCPP_BUILD_TESTS=ON
cmake --build build
ctest --test-dir build --output-on-failureCovered vectors:
- HMAC — RFC 4231
- PBKDF2 — RFC 6070
- HOTP — RFC 4226 (Appendix D)
- TOTP — RFC 6238 (Appendix B)
CI runs these on Linux/Windows/macOS.
example.cpp builds when HMACCPP_BUILD_EXAMPLES=ON.
#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 mac = hmac::get_hmac(key, input, hmac::TypeHash::SHA256);
bool ok = (mac.size() == 64) &&
hmac::constant_time_equal(
mac,
"7632ac2e8ddedaf4b3e7ab195fefd17571c37c970e02e169195a158ef59e53ca");
if (ok) std::cout << "MAC verified\n";
}Manual build after install:
g++ example.cpp -std=c++11 -I_install/include -L_install/lib -lhmac_cppMSVC:
cl /EHsc example.cpp /I _install\include /link /LIBPATH:_install\lib hmach_cpp.lib- Functions may throw
std::invalid_argument(bad params) andstd::runtime_error(internal errors). constant_time_equalassumes lengths are public; compare sizes first.- PBKDF2 limits:
dkLen ≤ (2^32−1)·hLen; iterations ≥ 1; salt length ≥ 16 recommended. - HKDF limits:
L ≤ 255·HashLen. - Thread-safety: functions are stateless and thread-safe given separate buffers.
- Original SHA-256: http://www.zedwood.com/article/cpp-sha256-function
- Original SHA-512: http://www.zedwood.com/article/cpp-sha512-function
- HMAC (wiki): https://en.wikipedia.org/wiki/HMAC
MIT — see LICENSE.