libdpf/include/dpf/dpf3_ds.hpp

126 lines
5.3 KiB
C++
Raw Permalink Normal View History

/// @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__