Checkpoint the party/runtime stack before share-program and malicious-mode work.
Ship the TLS mesh, composer, Beaver/Yao/leaf MPC, prep/online paths, apps, and docs so the tree is pushable before elevating share_expr, security_mode, and prep resume. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
695f8e84f7
commit
0d22946a0e
1835 changed files with 170291 additions and 2849 deletions
217
include/dpf/rss_seed.hpp
Normal file
217
include/dpf/rss_seed.hpp
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
/// @file dpf/rss_seed.hpp
|
||||
/// @brief Pairwise PRG seeds for honest-majority 3PC RSS preprocessing.
|
||||
/// @details Parties 0,1,2 hold keys `k01`, `k12`, `k20`. Party `i` derives
|
||||
/// both components of a replicated random value, a zero-sharing, and
|
||||
/// the local cross term of an RSS multiply with no message.
|
||||
#ifndef LIBDPF_INCLUDE_DPF_RSS_SEED_HPP__
|
||||
#define LIBDPF_INCLUDE_DPF_RSS_SEED_HPP__
|
||||
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
|
||||
#include "hedley/hedley.h"
|
||||
|
||||
#include "dpf/buffered_prg.hpp"
|
||||
#include "dpf/prg_aes.hpp"
|
||||
#include "dpf/random.hpp"
|
||||
#include "dpf/secret_share.hpp"
|
||||
|
||||
namespace dpf
|
||||
{
|
||||
namespace rss
|
||||
{
|
||||
|
||||
using seed_block = typename prg::aes128::block_type;
|
||||
|
||||
/// @brief Three pairwise master seeds. Role `i` holds seeds with `i±1 mod 3`.
|
||||
struct seed_bundle
|
||||
{
|
||||
seed_block k01{};
|
||||
seed_block k12{};
|
||||
seed_block k20{};
|
||||
};
|
||||
|
||||
/// @brief Sample three independent pairwise seeds (dealer / setup).
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
inline seed_bundle sample_seed_bundle()
|
||||
{
|
||||
seed_bundle b;
|
||||
b.k01 = randomness::sample_master_seed<prg::aes128>();
|
||||
b.k12 = randomness::sample_master_seed<prg::aes128>();
|
||||
b.k20 = randomness::sample_master_seed<prg::aes128>();
|
||||
return b;
|
||||
}
|
||||
|
||||
/// @brief Party `me`'s view: the two seeds it shares with its neighbors.
|
||||
struct party_seeds
|
||||
{
|
||||
unsigned me = 0;
|
||||
seed_block with_prev{}; ///< shared with (me+2)%3
|
||||
seed_block with_next{}; ///< shared with (me+1)%3
|
||||
|
||||
static party_seeds from_bundle(const seed_bundle & b, unsigned me)
|
||||
{
|
||||
if (me > 2)
|
||||
throw std::invalid_argument("rss party_seeds: me must be 0..2");
|
||||
party_seeds s;
|
||||
s.me = me;
|
||||
if (me == 0)
|
||||
{
|
||||
s.with_prev = b.k20;
|
||||
s.with_next = b.k01;
|
||||
}
|
||||
else if (me == 1)
|
||||
{
|
||||
s.with_prev = b.k01;
|
||||
s.with_next = b.k12;
|
||||
}
|
||||
else
|
||||
{
|
||||
s.with_prev = b.k12;
|
||||
s.with_next = b.k20;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
T derive(seed_block master, std::uint32_t role, std::uint64_t index)
|
||||
{
|
||||
randomness::lane_table<T, prg::aes128> table(master);
|
||||
return table.value_at(role, index);
|
||||
}
|
||||
|
||||
inline seed_block pair_seed(unsigned a, unsigned b, const seed_bundle & bundle)
|
||||
{
|
||||
const unsigned lo = a < b ? a : b;
|
||||
const unsigned hi = a < b ? b : a;
|
||||
if (lo == 0 && hi == 1)
|
||||
return bundle.k01;
|
||||
if (lo == 1 && hi == 2)
|
||||
return bundle.k12;
|
||||
if (lo == 0 && hi == 2)
|
||||
return bundle.k20;
|
||||
throw std::invalid_argument("rss pair_seed: bad pair");
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// @brief Replicated random `r` at `index`. Party `me` holds `(r_me, r_{me+1})`.
|
||||
template <typename T>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
replicated_share<T, 0> random_replicated0(const party_seeds & s, std::uint64_t index)
|
||||
{
|
||||
if (s.me != 0)
|
||||
throw std::invalid_argument("random_replicated0: wrong party");
|
||||
// r0 from k20 (parties 2,0), r1 from k01 (parties 0,1)
|
||||
const T r0 = detail::derive<T>(s.with_prev, 0, index);
|
||||
const T r1 = detail::derive<T>(s.with_next, 1, index);
|
||||
return replicated_share<T, 0>::from_raw(r0, r1);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
replicated_share<T, 1> random_replicated1(const party_seeds & s, std::uint64_t index)
|
||||
{
|
||||
if (s.me != 1)
|
||||
throw std::invalid_argument("random_replicated1: wrong party");
|
||||
const T r1 = detail::derive<T>(s.with_prev, 1, index);
|
||||
const T r2 = detail::derive<T>(s.with_next, 2, index);
|
||||
return replicated_share<T, 1>::from_raw(r1, r2);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
replicated_share<T, 2> random_replicated2(const party_seeds & s, std::uint64_t index)
|
||||
{
|
||||
if (s.me != 2)
|
||||
throw std::invalid_argument("random_replicated2: wrong party");
|
||||
const T r2 = detail::derive<T>(s.with_prev, 2, index);
|
||||
const T r0 = detail::derive<T>(s.with_next, 0, index);
|
||||
return replicated_share<T, 2>::from_raw(r2, r0);
|
||||
}
|
||||
|
||||
/// @brief Party-erased random replicated share.
|
||||
template <typename T>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
std::pair<T, T> random_replicated_components(const party_seeds & s,
|
||||
std::uint64_t index)
|
||||
{
|
||||
if (s.me == 0)
|
||||
{
|
||||
auto sh = random_replicated0<T>(s, index);
|
||||
return {sh.own, sh.next};
|
||||
}
|
||||
if (s.me == 1)
|
||||
{
|
||||
auto sh = random_replicated1<T>(s, index);
|
||||
return {sh.own, sh.next};
|
||||
}
|
||||
auto sh = random_replicated2<T>(s, index);
|
||||
return {sh.own, sh.next};
|
||||
}
|
||||
|
||||
/// @brief Zero-sharing for reshare: party `i` holds `z_i` with sum zero.
|
||||
/// @details `z_i = r_i - r_{i-1}` where `r` is a common pairwise stream on
|
||||
/// each edge; the three differences cancel.
|
||||
template <typename T>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
T zero_share(const party_seeds & s, std::uint64_t index)
|
||||
{
|
||||
// On edge with_next: parties me and next share stream role 0 → value α
|
||||
// On edge with_prev: parties me and prev share stream role 0 → value β
|
||||
// z_me = α - β so sum over the ring is zero.
|
||||
const T alpha = detail::derive<T>(s.with_next, 10u + s.me, index);
|
||||
const T beta = detail::derive<T>(s.with_prev, 10u + ((s.me + 2) % 3), index);
|
||||
return static_cast<T>(alpha - beta);
|
||||
}
|
||||
|
||||
/// @brief Local y-component of an RSS multiply before neighbor refresh.
|
||||
/// @details Party `i` holds `(x_i, x_{i+1})` and `(y_i, y_{i+1})`. The local
|
||||
/// product factor is `x_i*y_i + x_i*y_{i+1} + x_{i+1}*y_i` plus a
|
||||
/// zero-mask so the three factors sum to `xy` after refresh.
|
||||
template <typename T>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
T rss_mul_local(const party_seeds & s, T x_own, T x_next, T y_own, T y_next,
|
||||
std::uint64_t index)
|
||||
{
|
||||
const T cross = static_cast<T>(
|
||||
x_own * y_own + x_own * y_next + x_next * y_own);
|
||||
const T mask = zero_share<T>(s, index);
|
||||
return static_cast<T>(cross + mask);
|
||||
}
|
||||
|
||||
/// @brief Full dealer view: derive every party's components for tests.
|
||||
template <typename T>
|
||||
struct replicated_triple
|
||||
{
|
||||
replicated_share<T, 0> p0;
|
||||
replicated_share<T, 1> p1;
|
||||
replicated_share<T, 2> p2;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
HEDLEY_WARN_UNUSED_RESULT
|
||||
replicated_triple<T> random_replicated_all(const seed_bundle & b,
|
||||
std::uint64_t index)
|
||||
{
|
||||
auto s0 = party_seeds::from_bundle(b, 0);
|
||||
auto s1 = party_seeds::from_bundle(b, 1);
|
||||
auto s2 = party_seeds::from_bundle(b, 2);
|
||||
return replicated_triple<T>{
|
||||
random_replicated0<T>(s0, index),
|
||||
random_replicated1<T>(s1, index),
|
||||
random_replicated2<T>(s2, index)};
|
||||
}
|
||||
|
||||
} // namespace rss
|
||||
} // namespace dpf
|
||||
|
||||
#endif // LIBDPF_INCLUDE_DPF_RSS_SEED_HPP__
|
||||
Loading…
Add table
Add a link
Reference in a new issue