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
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Changelog

## [Unreleased]
### Added
- Base64 and Base32 encoding/decoding utilities with secure_buffer overloads.

## [0.3.0] - 2025-09-05
### Added
- PBKDF2 implementation.
Expand Down
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ set(HMAC_SOURCES
src/sha512.cpp
src/hmac.cpp
src/hmac_utils.cpp
src/encoding.cpp
)

set(HMAC_HEADERS
Expand All @@ -21,6 +22,7 @@ set(HMAC_HEADERS
include/hmac_cpp/sha256.hpp
include/hmac_cpp/sha512.hpp
include/hmac_cpp/secure_buffer.hpp
include/hmac_cpp/encoding.hpp
)

add_library(hmac_cpp ${HMAC_SOURCES})
Expand Down Expand Up @@ -58,6 +60,10 @@ endif()
add_executable(example_pbkdf2 example_pbkdf2.cpp)
target_link_libraries(example_pbkdf2 PRIVATE hmac_cpp)
target_include_directories(example_pbkdf2 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)

add_executable(example_encoding example_encoding.cpp)
target_link_libraries(example_encoding PRIVATE hmac_cpp)
target_include_directories(example_encoding PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include)
endif()

include(CMakePackageConfigHelpers)
Expand Down
13 changes: 13 additions & 0 deletions README-RU.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,19 @@ auto prk = hmac::hkdf_extract_sha256(ikm, salt);
auto okm = hmac::hkdf_expand_sha256(prk, /*info=*/{}, /*L=*/32); // L ≤ 255*HashLen
```

### Base64 / Base32

Утилиты для кодирования/декодирования Base64 (обычный и URL-алфавит) и Base32.

```cpp
#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);
```

### 🕓 HOTP / TOTP

OTP по RFC 4226/6238. **Секреты должны быть случайными** (не паролями). Если получаете Base32 (otpauth URI), декодируйте перед вызовом.
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,19 @@ auto prk = hmac::hkdf_extract_sha256(ikm, salt);
auto okm = hmac::hkdf_expand_sha256(prk, /*info=*/{}, /*L=*/32); // L ≤ 255*HashLen
```

### Base64 / Base32

Utility helpers for Base64 (standard or URL alphabet) and Base32.

```cpp
#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);
```

### 🕓 HOTP / TOTP

OTP per RFC 4226/6238. **Secrets should be random** (not passwords). If you receive Base32 (otpauth URI), decode before calling.
Expand Down
23 changes: 23 additions & 0 deletions example_encoding.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include <iostream>
#include <string>
#include <vector>
#include <hmac_cpp/encoding.hpp>
#include <hmac_cpp/secure_buffer.hpp>

int main() {
std::vector<uint8_t> data = {'f','o','o','b','a','r'};
std::string b64 = hmac_cpp::base64_encode(data);
std::cout << "Base64: " << b64 << std::endl;

std::vector<uint8_t> decoded;
hmac_cpp::base64_decode(b64, decoded);
std::cout << "Decoded: " << std::string(decoded.begin(), decoded.end()) << std::endl;

std::string b32 = hmac_cpp::base32_encode(data);
std::cout << "Base32: " << b32 << std::endl;

hmac_cpp::secure_buffer<uint8_t> sec;
hmac_cpp::base32_decode(b32, sec);
std::cout << "Decoded secure size: " << sec.size() << std::endl;
return 0;
}
102 changes: 102 additions & 0 deletions include/hmac_cpp/encoding.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
#ifndef _HMAC_ENCODING_HPP_INCLUDED
#define _HMAC_ENCODING_HPP_INCLUDED

#include "api.hpp"
#include "secure_buffer.hpp"
#include <cstdint>
#include <string>
#include <vector>

namespace hmac_cpp {

/// \brief Alphabet variant for Base64.
enum class Base64Alphabet { Standard, Url }; // Standard: "+/", Url: "-_"

// -------------------------
// Base64 — encode / decode
// -------------------------

/// \brief Base64-encode a byte buffer (RFC 4648).
/// \param data Pointer to input bytes.
/// \param len Number of input bytes.
/// \param alphabet Standard ("+/") or URL-safe ("-_") alphabet.
/// \param pad If true, append '=' padding to a multiple of 4 chars.
/// \return Encoded string.
HMAC_CPP_API std::string base64_encode(const uint8_t* data, size_t len,
Base64Alphabet alphabet = Base64Alphabet::Standard,
bool pad = true);

/// \brief Base64-encode a vector.
inline std::string base64_encode(const std::vector<uint8_t>& v,
Base64Alphabet alphabet = Base64Alphabet::Standard,
bool pad = true) {
return base64_encode(v.data(), v.size(), alphabet, pad);
}

/// \brief Base64-encode a secure_buffer.
inline std::string base64_encode(const secure_buffer<uint8_t>& v,
Base64Alphabet alphabet = Base64Alphabet::Standard,
bool pad = true) {
return base64_encode(v.data(), v.size(), alphabet, pad);
}

/// \brief Decode a Base64 string (RFC 4648).
/// \param in Input string (raw Base64 chars).
/// \param out Output byte vector (overwritten).
/// \param alphabet Standard ("+/") or URL-safe ("-_") alphabet.
/// \param require_padding If true, input must have proper '=' padding and length % 4 == 0.
/// \param strict If true, disallow whitespaces and enforce '=' only in the last quartet.
/// If false, ignore ASCII spaces and CR/LF/TAB and allow missing padding.
/// \return true on success, false on invalid input.
HMAC_CPP_API bool base64_decode(const std::string& in, std::vector<uint8_t>& out,
Base64Alphabet alphabet = Base64Alphabet::Standard,
bool require_padding = false,
bool strict = true) noexcept;

/// \brief Decode Base64 into secure_buffer.
HMAC_CPP_API bool base64_decode(const std::string& in, secure_buffer<uint8_t>& out,
Base64Alphabet alphabet = Base64Alphabet::Standard,
bool require_padding = false,
bool strict = true) noexcept;

// -------------------------
// Base32 — encode / decode
// -------------------------

/// \brief Base32-encode a byte buffer (RFC 4648; alphabet A–Z, 2–7).
/// \param data Pointer to input bytes.
/// \param len Number of input bytes.
/// \param pad If true, append '=' padding to a multiple of 8 chars.
/// \return Encoded string (upper-case).
HMAC_CPP_API std::string base32_encode(const uint8_t* data, size_t len,
bool pad = true);

/// \brief Base32-encode a vector.
inline std::string base32_encode(const std::vector<uint8_t>& v, bool pad = true) {
return base32_encode(v.data(), v.size(), pad);
}

/// \brief Base32-encode a secure_buffer.
inline std::string base32_encode(const secure_buffer<uint8_t>& v, bool pad = true) {
return base32_encode(v.data(), v.size(), pad);
}

/// \brief Decode a Base32 string (RFC 4648).
/// \param in Input string (Base32; upper-case preferred).
/// \param out Output byte vector (overwritten).
/// \param require_padding If true, input must have proper '=' padding and length % 8 == 0.
/// \param strict If true, disallow whitespaces and lower-case; enforce '=' only in the last block.
/// If false, ignore ASCII spaces and CR/LF/TAB and accept lower-case letters.
/// \return true on success, false on invalid input.
HMAC_CPP_API bool base32_decode(const std::string& in, std::vector<uint8_t>& out,
bool require_padding = false,
bool strict = true) noexcept;

/// \brief Decode Base32 into secure_buffer.
HMAC_CPP_API bool base32_decode(const std::string& in, secure_buffer<uint8_t>& out,
bool require_padding = false,
bool strict = true) noexcept;

} // namespace hmac_cpp

#endif // _HMAC_ENCODING_HPP_INCLUDED
1 change: 1 addition & 0 deletions include/hmac_cpp/secure_buffer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define HMAC_CPP_SECURE_BUFFER_HPP

#include <cstddef>
#include <cstdint>
#include <vector>
#include <type_traits>
#include <string>
Expand Down
Loading
Loading