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
15 changes: 14 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ set(HMAC_SOURCES
)

set(HMAC_HEADERS
include/hmac_cpp/api.hpp
include/hmac_cpp/hmac.hpp
include/hmac_cpp/hmac_utils.hpp
include/hmac_cpp/sha1.hpp
Expand All @@ -22,13 +23,25 @@ set(HMAC_HEADERS
include/hmac_cpp/secure_buffer.hpp
)

add_library(hmac_cpp STATIC ${HMAC_SOURCES})
add_library(hmac_cpp ${HMAC_SOURCES})
target_compile_features(hmac_cpp PUBLIC cxx_std_11)
target_include_directories(hmac_cpp PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)

if(BUILD_SHARED_LIBS)
target_compile_definitions(hmac_cpp PRIVATE HMAC_CPP_BUILD)
else()
target_compile_definitions(hmac_cpp PUBLIC HMAC_CPP_STATIC)
endif()

if(MSVC)
target_compile_options(hmac_cpp PRIVATE /wd4251)
else()
target_compile_options(hmac_cpp PRIVATE -fvisibility=hidden)
endif()

if(NOT TARGET hmac_cpp::hmac_cpp)
add_library(hmac_cpp::hmac_cpp ALIAS hmac_cpp)
endif()
Expand Down
18 changes: 18 additions & 0 deletions include/hmac_cpp/api.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#ifndef HMAC_CPP_API_HPP
#define HMAC_CPP_API_HPP

#if defined(_WIN32) || defined(__CYGWIN__)
#if defined(HMAC_CPP_STATIC)
#define HMAC_CPP_API
#elif defined(HMAC_CPP_BUILD)
#define HMAC_CPP_API __declspec(dllexport)
#else
#define HMAC_CPP_API __declspec(dllimport)
#endif
#elif defined(__GNUC__) && __GNUC__ >= 4
#define HMAC_CPP_API __attribute__((visibility("default")))
#else
#define HMAC_CPP_API
#endif

#endif // HMAC_CPP_API_HPP
13 changes: 7 additions & 6 deletions include/hmac_cpp/hmac.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <cstdint>
#include <string>
#include <vector>
#include "api.hpp"
#include "sha1.hpp"
#include "sha256.hpp"
#include "sha512.hpp"
Expand All @@ -22,20 +23,20 @@ namespace hmac_cpp {
/// \param input Input string
/// \param is_upper Flag for uppercase hex
/// \return Hexadecimal string
std::string to_hex(const std::string& input, bool is_upper = false);
HMAC_CPP_API std::string to_hex(const std::string& input, bool is_upper = false);

/// \brief Computes hash of the input string
/// \param input Input string
/// \param type Hash function type
/// \return Hash result
std::string get_hash(const std::string &input, TypeHash type);
HMAC_CPP_API std::string get_hash(const std::string &input, TypeHash type);

/// \brief Computes a hash of a raw buffer using the selected hash function
/// \param data Pointer to input data
/// \param length Length of the input data
/// \param type Hash function type
/// \return Binary hash result as std::vector<uint8_t>
std::vector<uint8_t> get_hash(const void* data, size_t length, TypeHash type);
HMAC_CPP_API std::vector<uint8_t> get_hash(const void* data, size_t length, TypeHash type);

/// \brief Computes a hash of a vector using the selected hash function.
/// \tparam T Type of the vector element (char or uint8_t).
Expand All @@ -51,7 +52,7 @@ namespace hmac_cpp {
}

/// \brief Streaming HMAC computation context.
class HmacContext {
class HMAC_CPP_API HmacContext {
public:
explicit HmacContext(TypeHash type) : type_(type), block_size_(0), digest_size_(0) {}

Expand Down Expand Up @@ -88,7 +89,7 @@ namespace hmac_cpp {
/// \param type Hash function type
/// \return HMAC result as a vector of bytes
/// \throws std::invalid_argument If any pointer is null while the corresponding length is non-zero
std::vector<uint8_t> get_hmac(const void* key_ptr, size_t key_len, const void* msg_ptr, size_t msg_len, TypeHash type);
HMAC_CPP_API std::vector<uint8_t> get_hmac(const void* key_ptr, size_t key_len, const void* msg_ptr, size_t msg_len, TypeHash type);

/// \brief Computes HMAC from key and message byte vectors using the specified hash function
/// \tparam T Byte type: must be either char or uint8_t
Expand All @@ -111,7 +112,7 @@ namespace hmac_cpp {
/// \param is_hex Return result in hex format
/// \param is_upper Use uppercase hex
/// \return HMAC result
std::string get_hmac(const std::vector<uint8_t>& key, const std::string &msg, TypeHash type, bool is_hex = true, bool is_upper = false);
HMAC_CPP_API std::string get_hmac(const std::vector<uint8_t>& key, const std::string &msg, TypeHash type, bool is_hex = true, bool is_upper = false);

/// \brief Computes HMAC from secure_buffer key
inline std::string get_hmac(const secure_buffer<uint8_t>& key, const std::string &msg, TypeHash type, bool is_hex = true, bool is_upper = false) {
Expand Down
34 changes: 17 additions & 17 deletions include/hmac_cpp/hmac_utils.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace hmac_cpp {
/// \param b Pointer to second array
/// \param b_len Length of the second array
/// \return true if both arrays are equal
bool constant_time_equals(const uint8_t* a, size_t a_len,
HMAC_CPP_API bool constant_time_equals(const uint8_t* a, size_t a_len,
const uint8_t* b, size_t b_len);

inline bool constant_time_equals(const std::vector<uint8_t>& a,
Expand Down Expand Up @@ -77,7 +77,7 @@ namespace hmac_cpp {
/// \param dk_len Desired length of the derived key in bytes, must be positive
/// \param hash_type Hash function to use (SHA1, SHA256, SHA512)
/// \return Derived key as a vector of bytes
std::vector<uint8_t> pbkdf2(
HMAC_CPP_API std::vector<uint8_t> pbkdf2(
const void* password_ptr, size_t password_len,
const void* salt_ptr, size_t salt_len,
uint32_t iterations, size_t dk_len,
Expand Down Expand Up @@ -163,7 +163,7 @@ namespace hmac_cpp {
/// \param out_ptr Output buffer for derived key
/// \param dk_len Length of output buffer in bytes, must be positive
/// \return true on success, false on invalid parameters
bool pbkdf2(Pbkdf2Hash prf,
HMAC_CPP_API bool pbkdf2(Pbkdf2Hash prf,
const void* password_ptr, size_t password_len,
const void* salt_ptr, size_t salt_len,
uint32_t iterations, uint8_t* out_ptr, size_t dk_len) noexcept;
Expand Down Expand Up @@ -211,7 +211,7 @@ namespace hmac_cpp {
/// \param out_ptr Output buffer for derived key
/// \param dk_len Length of output buffer in bytes, must be positive
/// \return true on success, false on invalid parameters
bool pbkdf2_hmac_sha256(const void* password_ptr, size_t password_len,
HMAC_CPP_API bool pbkdf2_hmac_sha256(const void* password_ptr, size_t password_len,
const void* salt_ptr, size_t salt_len,
uint32_t iterations, uint8_t* out_ptr, size_t dk_len) noexcept;

Expand Down Expand Up @@ -271,7 +271,7 @@ namespace hmac_cpp {
/// \param dk_len Desired length of the derived key in bytes, must be positive.
/// \param prf Hash function to use (SHA1, SHA256, SHA512).
/// \return Derived key as a vector of bytes.
std::vector<uint8_t> pbkdf2_with_pepper(
HMAC_CPP_API std::vector<uint8_t> pbkdf2_with_pepper(
const void* password_ptr, size_t password_len,
const void* salt_ptr, size_t salt_len,
const void* pepper_ptr, size_t pepper_len,
Expand Down Expand Up @@ -343,7 +343,7 @@ namespace hmac_cpp {
/// \param salt_ptr Pointer to optional salt buffer (may be null when salt_len is 0).
/// \param salt_len Length of the salt in bytes.
/// \return Pseudorandom key (PRK) as a byte vector.
std::vector<uint8_t> hkdf_extract_sha256(
HMAC_CPP_API std::vector<uint8_t> hkdf_extract_sha256(
const void* ikm_ptr, size_t ikm_len,
const void* salt_ptr, size_t salt_len);

Expand All @@ -360,7 +360,7 @@ namespace hmac_cpp {
/// \param info_len Length of the info buffer in bytes.
/// \param L Length of output keying material in bytes.
/// \return Output keying material as a byte vector.
std::vector<uint8_t> hkdf_expand_sha256(
HMAC_CPP_API std::vector<uint8_t> hkdf_expand_sha256(
const void* prk_ptr, size_t prk_len,
const void* info_ptr, size_t info_len,
size_t L);
Expand Down Expand Up @@ -401,7 +401,7 @@ namespace hmac_cpp {
/// \param hash_type Hash function to use (SHA1, SHA256, SHA512). Default is SHA256
/// \return Hex-encoded HMAC-SHA256 of the rounded time value
/// \throws std::runtime_error if the system time cannot be retrieved
std::string generate_time_token(const std::vector<uint8_t>& key, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256);
HMAC_CPP_API std::string generate_time_token(const std::vector<uint8_t>& key, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256);
inline std::string generate_time_token(const secure_buffer<uint8_t>& key, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256) {
return generate_time_token(std::vector<uint8_t>(key.begin(), key.end()), interval_sec, hash_type);
}
Expand All @@ -418,7 +418,7 @@ namespace hmac_cpp {
/// \param hash_type Hash function to use (SHA1, SHA256, SHA512). Default is SHA256
/// \return true if the token is valid within the ±1 interval range; false otherwise
/// \throws std::runtime_error if the system time cannot be retrieved
bool is_token_valid(const std::string &token, const std::vector<uint8_t>& key, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256);
HMAC_CPP_API bool is_token_valid(const std::string &token, const std::vector<uint8_t>& key, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256);
inline bool is_token_valid(const std::string &token, const secure_buffer<uint8_t>& key, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256) {
return is_token_valid(token, std::vector<uint8_t>(key.begin(), key.end()), interval_sec, hash_type);
}
Expand All @@ -435,7 +435,7 @@ namespace hmac_cpp {
/// \param hash_type Hash function to use (SHA1, SHA256, SHA512). Default is SHA256
/// \return Hex-encoded HMAC-SHA256 of the concatenated timestamp and fingerprint
/// \throws std::runtime_error if the system time cannot be retrieved
std::string generate_time_token(const std::vector<uint8_t>& key, const std::string &fingerprint, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256);
HMAC_CPP_API std::string generate_time_token(const std::vector<uint8_t>& key, const std::string &fingerprint, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256);
inline std::string generate_time_token(const secure_buffer<uint8_t>& key, const std::string &fingerprint, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256) {
return generate_time_token(std::vector<uint8_t>(key.begin(), key.end()), fingerprint, interval_sec, hash_type);
}
Expand All @@ -453,7 +453,7 @@ namespace hmac_cpp {
/// \param hash_type Hash function to use (SHA1, SHA256, SHA512). Default is SHA256
/// \return true if the token is valid within the ±1 interval range; false otherwise
/// \throws std::runtime_error if the system time cannot be retrieved
bool is_token_valid(const std::string &token, const std::vector<uint8_t>& key, const std::string &fingerprint, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256);
HMAC_CPP_API bool is_token_valid(const std::string &token, const std::vector<uint8_t>& key, const std::string &fingerprint, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256);
inline bool is_token_valid(const std::string &token, const secure_buffer<uint8_t>& key, const std::string &fingerprint, int interval_sec = 60, TypeHash hash_type = TypeHash::SHA256) {
return is_token_valid(token, std::vector<uint8_t>(key.begin(), key.end()), fingerprint, interval_sec, hash_type);
}
Expand All @@ -470,7 +470,7 @@ namespace hmac_cpp {
/// \param digits Desired number of digits in the OTP (typically 6–8, max 9)
/// \param hash_type Hash function to use (SHA1, SHA256, SHA512). Default is SHA1
/// \return One-Time Password (OTP) as an integer in the range [0, 10^digits)
int get_hotp_code(const void* key_ptr, size_t key_len, uint64_t counter, int digits = 6, TypeHash hash_type = TypeHash::SHA1);
HMAC_CPP_API int get_hotp_code(const void* key_ptr, size_t key_len, uint64_t counter, int digits = 6, TypeHash hash_type = TypeHash::SHA1);

/// \brief Computes HOTP code from a vector of bytes as key (RFC 4226)
/// \tparam T Must be either `char` or `uint8_t`
Expand Down Expand Up @@ -508,7 +508,7 @@ namespace hmac_cpp {
/// \param digits Desired number of digits in the OTP (1-9)
/// \return One-Time Password (OTP) as an integer
/// \throws std::runtime_error if the digest is too short for dynamic truncation
int hotp_from_digest(const std::vector<uint8_t>& hmac_result, int digits);
HMAC_CPP_API int hotp_from_digest(const std::vector<uint8_t>& hmac_result, int digits);
}

/// \brief Computes TOTP (Time-Based One-Time Password) code for a specific timestamp
Expand All @@ -521,7 +521,7 @@ namespace hmac_cpp {
/// \param hash_type Hash function to use (SHA1, SHA256, SHA512; default: SHA1)
/// \return TOTP code as an integer
/// \throws std::invalid_argument if period <= 0 or digits not in [1,9]
int get_totp_code_at(
HMAC_CPP_API int get_totp_code_at(
const void* key_ptr,
size_t key_len,
uint64_t timestamp,
Expand Down Expand Up @@ -587,7 +587,7 @@ namespace hmac_cpp {
/// \return TOTP code as an integer.
/// \throws std::invalid_argument if period <= 0 or digits not in [1,9].
/// \throws std::runtime_error if the system time cannot be retrieved.
int get_totp_code(
HMAC_CPP_API int get_totp_code(
const void* key_ptr,
size_t key_len,
int period = 30,
Expand Down Expand Up @@ -638,7 +638,7 @@ namespace hmac_cpp {
/// The +1 step check is skipped when the computed counter equals
/// std::numeric_limits<uint64_t>::max().
/// \throws std::invalid_argument if period <= 0 or digits not in [1,9]
bool is_totp_token_valid(
HMAC_CPP_API bool is_totp_token_valid(
int token,
const void* key_ptr,
size_t key_len,
Expand Down Expand Up @@ -728,7 +728,7 @@ namespace hmac_cpp {
/// std::numeric_limits<uint64_t>::max().
/// \throws std::invalid_argument if period <= 0 or digits not in [1,9]
/// \throws std::runtime_error if the system time cannot be retrieved
bool is_totp_token_valid(
HMAC_CPP_API bool is_totp_token_valid(
int token,
const void* key_ptr,
size_t key_len,
Expand Down
9 changes: 5 additions & 4 deletions include/hmac_cpp/sha1.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@
#include <string>
#include <vector>
#include <cstdint>
#include "api.hpp"

namespace hmac_hash {

/// \brief Class for computing SHA1 hash
class SHA1 {
class HMAC_CPP_API SHA1 {
public:

/// \brief Initializes SHA1 context
Expand Down Expand Up @@ -60,18 +61,18 @@ namespace hmac_hash {
/// \param data Pointer to input data
/// \param length Length of the input data
/// \param digest Output buffer of size SHA1::DIGEST_SIZE
void sha1(const void* data, size_t length, uint8_t* digest);
HMAC_CPP_API void sha1(const void* data, size_t length, uint8_t* digest);

/// \brief Computes SHA1 hash of a raw byte buffer
/// \param data Pointer to input data
/// \param length Length of the input data
/// \return Vector containing the SHA1 digest
std::vector<uint8_t> sha1(const void* data, size_t length);
HMAC_CPP_API std::vector<uint8_t> sha1(const void* data, size_t length);

/// \brief Computes SHA1 hash of a string
/// \param input Input string
/// \return Hash as a binary string
std::string sha1(const std::string &input);
HMAC_CPP_API std::string sha1(const std::string &input);

/// \brief Computes SHA1 hash of a vector of bytes
/// \tparam T Type of the vector element (char or uint8_t)
Expand Down
9 changes: 5 additions & 4 deletions include/hmac_cpp/sha256.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,12 @@
#include <string>
#include <vector>
#include <cstdint>
#include "api.hpp"

namespace hmac_hash {

/// \brief Class for computing SHA256 hash
class SHA256 {
class HMAC_CPP_API SHA256 {
protected:
const static uint32_t sha256_k[];

Expand Down Expand Up @@ -83,18 +84,18 @@ namespace hmac_hash {
/// \param data Pointer to input data
/// \param length Length of the input data
/// \param digest Output buffer of size SHA256::DIGEST_SIZE
void sha256(const void* data, size_t length, uint8_t* digest);
HMAC_CPP_API void sha256(const void* data, size_t length, uint8_t* digest);

/// \brief Computes SHA256 hash of a raw byte buffer
/// \param data Pointer to input data
/// \param length Length of the input data
/// \return Vector containing the SHA256 digest
std::vector<uint8_t> sha256(const void* data, size_t length);
HMAC_CPP_API std::vector<uint8_t> sha256(const void* data, size_t length);

/// \brief Computes SHA256 hash of a string
/// \param input Input string
/// \return Hash as a binary string
std::string sha256(const std::string &input);
HMAC_CPP_API std::string sha256(const std::string &input);

/// \brief Computes SHA256 hash of a vector of bytes
/// \tparam T Type of the vector element (char or uint8_t)
Expand Down
9 changes: 5 additions & 4 deletions include/hmac_cpp/sha512.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,15 @@
#include <string>
#include <vector>
#include <cstdint>
#include "api.hpp"

namespace hmac_hash {

/// \brief SHA512 hashing class
///
/// SHA-512 is the largest hash function in the SHA-2 family.
/// It provides 256-bit security for digital signatures and hash-only applications.
class SHA512 {
class HMAC_CPP_API SHA512 {
protected:
const static uint64_t sha512_k[];

Expand Down Expand Up @@ -86,18 +87,18 @@ namespace hmac_hash {
/// \param data Pointer to input data
/// \param length Length of the input data
/// \param digest Output buffer of size SHA512::DIGEST_SIZE
void sha512(const void* data, size_t length, uint8_t* digest);
HMAC_CPP_API void sha512(const void* data, size_t length, uint8_t* digest);

/// \brief Computes SHA512 hash of a raw byte buffer
/// \param data Pointer to input data
/// \param length Length of the input data
/// \return Vector containing the SHA512 digest
std::vector<uint8_t> sha512(const void* data, size_t length);
HMAC_CPP_API std::vector<uint8_t> sha512(const void* data, size_t length);

/// \brief Computes SHA512 hash of a string
/// \param input Input string
/// \return Hash as a binary string
std::string sha512(const std::string &input);
HMAC_CPP_API std::string sha512(const std::string &input);

/// \brief Computes SHA512 hash of a vector of bytes
/// \tparam T Type of the vector element (char or uint8_t)
Expand Down
Loading