libdpf/include/dpf/blob.hpp

150 lines
3.8 KiB
C++
Raw Normal View History

/// @file dpf/blob.hpp
/// @brief Fixed-length XOR byte-string leaf (`dpf::blob<N>`).
/// @details A mailbox row or other byte payload that does not fit in one AES
/// block. Keygen stretches each final seed with the exterior PRG
/// (counter mode) into `N` bytes and XORs a correction of that
/// length, matching Express's `genDPF` leaf. The tree and depth are
/// unchanged: Boyle packing uses `ceil(8N / λ)` exterior blocks and
/// `lg(outputs_per_leaf) = 0`.
/// @copyright Copyright (c) 2019-2026 Ryan Henry and [others](@ref authors)
/// @license Released under a GNU General Public v2.0 (GPLv2) license.
#ifndef LIBDPF_INCLUDE_DPF_BLOB_HPP__
#define LIBDPF_INCLUDE_DPF_BLOB_HPP__
#include <array>
#include <cstddef>
#include <cstring>
#include <type_traits>
#include "hedley/hedley.h"
#include "dpf/utils.hpp"
namespace dpf
{
/// @brief XOR share of an `N`-byte string.
/// @tparam N byte length (`N >= 1`)
template <std::size_t N>
struct blob
{
static_assert(N >= 1, "dpf::blob: N must be at least 1");
static constexpr std::size_t size = N;
std::array<unsigned char, N> bytes{};
HEDLEY_NO_THROW
constexpr blob() noexcept = default;
HEDLEY_NO_THROW
explicit blob(const unsigned char * src, std::size_t n = N) noexcept
{
const std::size_t m = n < N ? n : N;
if (m != 0)
std::memcpy(bytes.data(), src, m);
}
HEDLEY_NO_THROW
explicit blob(std::array<unsigned char, N> b) noexcept
: bytes{std::move(b)}
{ }
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
unsigned char * data() noexcept { return bytes.data(); }
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
const unsigned char * data() const noexcept { return bytes.data(); }
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
friend constexpr bool operator==(const blob & a, const blob & b) noexcept
{
for (std::size_t i = 0; i < N; ++i)
if (a.bytes[i] != b.bytes[i])
return false;
return true;
}
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
friend constexpr bool operator!=(const blob & a, const blob & b) noexcept
{
return !(a == b);
}
/// @brief XOR (group addition / subtraction for this leaf).
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
friend blob operator^(const blob & a, const blob & b) noexcept
{
blob out;
for (std::size_t i = 0; i < N; ++i)
out.bytes[i] = static_cast<unsigned char>(a.bytes[i] ^ b.bytes[i]);
return out;
}
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
friend blob operator+(const blob & a, const blob & b) noexcept
{
return a ^ b;
}
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
friend blob operator-(const blob & a, const blob & b) noexcept
{
return a ^ b;
}
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
blob & operator^=(const blob & o) noexcept
{
*this = *this ^ o;
return *this;
}
HEDLEY_NO_THROW
HEDLEY_ALWAYS_INLINE
blob & operator+=(const blob & o) noexcept
{
return (*this) ^= o;
}
};
template <typename T>
struct is_blob : std::false_type {};
template <std::size_t N>
struct is_blob<blob<N>> : std::true_type {};
template <typename T>
inline constexpr bool is_blob_v = is_blob<std::decay_t<T>>::value;
namespace utils
{
template <std::size_t N>
struct bitlength_of<dpf::blob<N>>
: public std::integral_constant<std::size_t, N * 8>
{ };
template <std::size_t N, typename NodeT>
struct bitlength_of_output<dpf::blob<N>, NodeT>
: public std::integral_constant<std::size_t, N * 8>
{ };
template <std::size_t N>
struct has_characteristic_two<dpf::blob<N>> : std::true_type
{ };
template <std::size_t N>
struct is_xor_wrapper<dpf::blob<N>> : std::true_type
{ };
} // namespace utils
} // namespace dpf
#endif // LIBDPF_INCLUDE_DPF_BLOB_HPP__