78 lines
2.5 KiB
C++
78 lines
2.5 KiB
C++
|
|
/// @file dpf/bit_inject.hpp
|
|||
|
|
/// @brief Boolean bit × arithmetic value (2PC bit_mul and 3PC RSS injection).
|
|||
|
|
#ifndef LIBDPF_INCLUDE_DPF_BIT_INJECT_HPP__
|
|||
|
|
#define LIBDPF_INCLUDE_DPF_BIT_INJECT_HPP__
|
|||
|
|
|
|||
|
|
#include <cstddef>
|
|||
|
|
#include <cstdint>
|
|||
|
|
#include <utility>
|
|||
|
|
|
|||
|
|
#include "hedley/hedley.h"
|
|||
|
|
|
|||
|
|
#include "dpf/beaver.hpp"
|
|||
|
|
#include "dpf/rss_seed.hpp"
|
|||
|
|
#include "dpf/secret_share.hpp"
|
|||
|
|
|
|||
|
|
namespace dpf
|
|||
|
|
{
|
|||
|
|
namespace bit_inject
|
|||
|
|
{
|
|||
|
|
|
|||
|
|
/// @brief 2PC: `b * x` via a beaver bit_mul on an existing session.
|
|||
|
|
template <typename Ring>
|
|||
|
|
HEDLEY_WARN_UNUSED_RESULT
|
|||
|
|
beavers::wire<Ring> inject2(beavers::session<Ring> & s,
|
|||
|
|
beavers::wire<Ring> bit_wire, beavers::wire<Ring> arith_wire)
|
|||
|
|
{
|
|||
|
|
return s.bit_mul(bit_wire, arith_wire);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// @brief Local y-factor of RSS bit injection before ring send.
|
|||
|
|
/// @details Party holds RSS bit `(b_own, b_next)` and arithmetic `(x_own, x_next)`.
|
|||
|
|
/// Local contribution mirrors RSS mul with the bit as a 0/1 factor.
|
|||
|
|
template <typename T>
|
|||
|
|
HEDLEY_WARN_UNUSED_RESULT
|
|||
|
|
T rss_inject_local(const rss::party_seeds & seeds, T b_own, T b_next,
|
|||
|
|
T x_own, T x_next, std::uint64_t index)
|
|||
|
|
{
|
|||
|
|
// Treat bit components as ring elements in {0,1}.
|
|||
|
|
return rss::rss_mul_local(seeds, b_own, b_next, x_own, x_next, index);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// @brief After ring refresh: party receives `y_prev` and forms RSS `(y_own, y_prev)`
|
|||
|
|
/// wait — standard RSS refresh: send y_own to next, receive from prev,
|
|||
|
|
/// store `(y_own, y_from_prev)`? Actually ABY3: party i holds y_i after
|
|||
|
|
/// local mul; sends y_i to party i-1; ends with (y_i, y_{i+1}).
|
|||
|
|
template <typename T>
|
|||
|
|
HEDLEY_WARN_UNUSED_RESULT
|
|||
|
|
std::pair<T, T> rss_refresh(T y_own, T y_from_next)
|
|||
|
|
{
|
|||
|
|
return {y_own, y_from_next};
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// @brief Cleartext identity: `(b0⊕b1) * (x0+x1)`.
|
|||
|
|
template <typename Ring>
|
|||
|
|
HEDLEY_WARN_UNUSED_RESULT
|
|||
|
|
Ring inject_clear(std::uint8_t b0, std::uint8_t b1, Ring x0, Ring x1)
|
|||
|
|
{
|
|||
|
|
const Ring b = static_cast<Ring>((b0 ^ b1) & 1u);
|
|||
|
|
return static_cast<Ring>(b * (x0 + x1));
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// @brief Boolean RSS AND local factor (GF(2)).
|
|||
|
|
inline std::uint8_t rss_and_local(const rss::party_seeds & seeds,
|
|||
|
|
std::uint8_t a_own, std::uint8_t a_next, std::uint8_t b_own,
|
|||
|
|
std::uint8_t b_next, std::uint64_t index)
|
|||
|
|
{
|
|||
|
|
const std::uint8_t cross = static_cast<std::uint8_t>(
|
|||
|
|
(a_own & b_own) ^ (a_own & b_next) ^ (a_next & b_own));
|
|||
|
|
const std::uint8_t mask = static_cast<std::uint8_t>(
|
|||
|
|
rss::zero_share<std::uint8_t>(seeds, index) & 1u);
|
|||
|
|
return static_cast<std::uint8_t>(cross ^ mask);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
} // namespace bit_inject
|
|||
|
|
} // namespace dpf
|
|||
|
|
|
|||
|
|
#endif // LIBDPF_INCLUDE_DPF_BIT_INJECT_HPP__
|