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>
125 lines
5.3 KiB
C++
125 lines
5.3 KiB
C++
/// @file dpf/dpf3_ds.hpp
|
||
/// @brief Dual-spine Doerner–Shelat generation of (2,3) point keys.
|
||
/// @note Two independent openings, one per spine of Zyskind, Yanai, and Pentland (ePrint 2024/1658, Figure 3). Each opening follows Doerner and shelat, CCS 2017 (ePrint 2017/827).
|
||
/// @details Runs two independent two-party DS walks (spines A and B) with
|
||
/// Fig-3 `τ` payloads, then assembles the three evaluator keys via
|
||
/// `assemble_from_spines`. Matches honest-dealer `make_dpf3` on the
|
||
/// opened point `x0 ⊕ x1` (after the signed-MSB flip on share 0).
|
||
/// @copyright Copyright (c) 2019-2026 Ryan Henry and [others](@ref authors)
|
||
/// @license Released under a GNU General Public v2.0 (GPLv2) license;
|
||
/// see [LICENSE.md](@ref license) for details.
|
||
|
||
#ifndef LIBDPF_INCLUDE_DPF_DPF3_DS_HPP__
|
||
#define LIBDPF_INCLUDE_DPF_DPF3_DS_HPP__
|
||
|
||
#include <tuple>
|
||
#include <type_traits>
|
||
#include <utility>
|
||
|
||
#include "hedley/hedley.h"
|
||
|
||
#include "dpf/dpf3.hpp"
|
||
#include "dpf/fp61.hpp"
|
||
#include "dpf/incremental.hpp"
|
||
#include "dpf/placement.hpp"
|
||
#include "dpf/prg_aes.hpp"
|
||
#include "dpf/verifiable.hpp"
|
||
#include "dpf/wildcard.hpp"
|
||
|
||
namespace dpf
|
||
{
|
||
namespace detail
|
||
{
|
||
namespace dpf3_impl
|
||
{
|
||
|
||
template <typename InteriorPRG, typename ExteriorPRG, typename InputT,
|
||
bool Verifiable, bool Updatable, bool Extractable>
|
||
auto make_point3_ds(InputT x0, InputT x1, fp61 beta)
|
||
{
|
||
using X = xor61;
|
||
const InputT alpha = open_xor_point(x0, x1);
|
||
const tau_quad t = sample_taus(beta);
|
||
const X payload_a = t.t0 + t.t1;
|
||
const X payload_b = t.t2 + t.t3;
|
||
|
||
if constexpr (Updatable)
|
||
{
|
||
// Classic DS rejects wildcards; the incremental path plants beaver
|
||
// leaves. Inner verifiable tags match the outer `Verifiable` flag.
|
||
auto A = [&] {
|
||
if constexpr (Verifiable)
|
||
return dpf::make_dpf_doerner_shelat<InteriorPRG, ExteriorPRG>(
|
||
x0, x1, dpf::wildcard_value<X>{}, dpf::verifiable{});
|
||
else
|
||
return dpf::make_dpf_doerner_shelat<InteriorPRG, ExteriorPRG>(
|
||
x0, x1, dpf::wildcard_value<X>{});
|
||
}();
|
||
auto B = [&] {
|
||
if constexpr (Verifiable)
|
||
return dpf::make_dpf_doerner_shelat<InteriorPRG, ExteriorPRG>(
|
||
x0, x1, dpf::wildcard_value<X>{}, dpf::verifiable{});
|
||
else
|
||
return dpf::make_dpf_doerner_shelat<InteriorPRG, ExteriorPRG>(
|
||
x0, x1, dpf::wildcard_value<X>{});
|
||
}();
|
||
assign_xor_payload(A.first, A.second, payload_a);
|
||
assign_xor_payload(B.first, B.second, payload_b);
|
||
return assemble_from_spines<Verifiable, Extractable, true>(
|
||
std::move(A.first), std::move(A.second), std::move(B.first),
|
||
std::move(B.second), t, alpha);
|
||
}
|
||
else
|
||
{
|
||
auto A = [&] {
|
||
if constexpr (Verifiable)
|
||
return dpf::make_dpf_doerner_shelat<InteriorPRG, ExteriorPRG>(
|
||
x0, x1, payload_a, dpf::verifiable{});
|
||
else
|
||
return dpf::make_dpf_doerner_shelat<InteriorPRG, ExteriorPRG>(
|
||
x0, x1, payload_a);
|
||
}();
|
||
auto B = [&] {
|
||
if constexpr (Verifiable)
|
||
return dpf::make_dpf_doerner_shelat<InteriorPRG, ExteriorPRG>(
|
||
x0, x1, payload_b, dpf::verifiable{});
|
||
else
|
||
return dpf::make_dpf_doerner_shelat<InteriorPRG, ExteriorPRG>(
|
||
x0, x1, payload_b);
|
||
}();
|
||
return assemble_from_spines<Verifiable, Extractable, false>(
|
||
std::move(A.first), std::move(A.second), std::move(B.first),
|
||
std::move(B.second), t, alpha);
|
||
}
|
||
}
|
||
|
||
} // namespace dpf3_impl
|
||
} // namespace detail
|
||
|
||
/// @brief Dual-spine Doerner–Shelat (2,3) keys for XOR shares of `α`.
|
||
/// @details `α = x0 ⊕ x1` after the signed-MSB flip on `x0`. Tags match
|
||
/// `make_dpf3`: `verifiable`, `extractable`, and `updatable`, any order.
|
||
/// \complexity O(n) time. One `ds_advance_level` per level: two PRG expansions and one `prepare_level`. n is `depth`.
|
||
/// \rounds No sockets. This is the in-process transcript. A networked walk is `dpf::party::dist::point_party`.
|
||
/// \communication none here. `local_cw_protocol` opens the correction word locally.
|
||
/// \preprocessing Per level, `prepare_level` draws one `ds_cw_pads` (two parties × a 128-bit rand, a 128-bit gamma, and a bit) and two `ds_and_pads`. Arithmetic inputs also run a carry chain of n-1 bit-AND triples in `encode_walk_shares`.
|
||
template <typename InteriorPRG = dpf::prg::aes128,
|
||
typename ExteriorPRG = InteriorPRG,
|
||
typename InputT,
|
||
typename ...Tags>
|
||
HEDLEY_WARN_UNUSED_RESULT
|
||
auto make_dpf3_doerner_shelat(InputT x0, InputT x1, fp61 beta, Tags ...tags)
|
||
{
|
||
using flags = detail::dpf3_impl::tag_flags<Tags...>;
|
||
static_assert(flags::known,
|
||
"make_dpf3_doerner_shelat tags are verifiable, extractable, updatable");
|
||
static_assert(sizeof...(Tags) == flags::counted,
|
||
"make_dpf3_doerner_shelat: repeated tag");
|
||
(void)std::initializer_list<int>{((void)tags, 0)...};
|
||
return detail::dpf3_impl::make_point3_ds<InteriorPRG, ExteriorPRG, InputT,
|
||
flags::verifiable, flags::updatable, flags::extractable>(x0, x1, beta);
|
||
}
|
||
|
||
} // namespace dpf
|
||
|
||
#endif // LIBDPF_INCLUDE_DPF_DPF3_DS_HPP__
|