/// @file dpf/it_dpf3.hpp /// @brief Information-theoretic 3-server distributed point function. /// @details Statistically private among three servers: any one key is /// independent of `(α, β)`, and the **sum** of all three evaluations /// is the point function (Boyle–Gilboa–Ishai–Kolobov, ePrint 2023/028). /// Distinct from the computational `(2,3)` Shamir key `make_dpf3` /// (ePrint 2024/1658), where any two shares reconstruct. Domain /// `uint8_t`, payload `uint64_t`. For this domain size the share is a /// full additive truth table (no GGM correction words); the paper's /// matching-vector packing targets asymptotically large `N`. /// @see dpf/dpf3.hpp, examples/applications/it_pir3.cpp, examples/applications/pir3.cpp /// @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_IT_DPF3_HPP__ #define LIBDPF_INCLUDE_DPF_IT_DPF3_HPP__ #include #include #include #include #include #include "hedley/hedley.h" #include "dpf/random.hpp" #include "dpf/secret_share.hpp" namespace dpf { /// @brief One evaluator's key for the information-theoretic 3-server DPF. struct it_dpf3_key { static constexpr std::size_t domain_size = 256; using input_type = std::uint8_t; using output_type = std::uint64_t; std::uint8_t party = 0; std::array share{}; }; /// @brief Three additive keys for `f_{α,β}` on `{0..255} → uint64_t`. /// @details `eval_it_dpf3(k0,x) + eval_it_dpf3(k1,x) + eval_it_dpf3(k2,x)` equals /// `β` at `x = α` and `0` elsewhere (wrapping `uint64_t` arithmetic). /// \complexity O(N) samples for domain size `N = 256`. Key size is `N` words /// per party (truth-table share), not subpolynomial. HEDLEY_WARN_UNUSED_RESULT inline auto make_it_dpf3(std::uint8_t alpha, std::uint64_t beta) { it_dpf3_key k0; it_dpf3_key k1; it_dpf3_key k2; k0.party = 0; k1.party = 1; k2.party = 2; for (std::size_t x = 0; x < it_dpf3_key::domain_size; ++x) { const std::uint64_t secret = (static_cast(x) == alpha) ? beta : 0; auto [a, b, c] = additively_share3(secret); k0.share[x] = a.raw(); k1.share[x] = b.raw(); k2.share[x] = c.raw(); } return std::make_tuple(std::move(k0), std::move(k1), std::move(k2)); } /// @brief One additive share of `f_{α,β}(x)`. /// \complexity O(1). HEDLEY_ALWAYS_INLINE HEDLEY_NO_THROW HEDLEY_WARN_UNUSED_RESULT constexpr std::uint64_t eval_it_dpf3(const it_dpf3_key & key, std::uint8_t x) noexcept { return key.share[x]; } /// @brief `sum_x eval_it_dpf3(key, x) * weights[x]` over the whole domain. /// \complexity O(N) multiply-adds, `N = 256`. template HEDLEY_WARN_UNUSED_RESULT auto eval_it_dpf3_inner_product(const it_dpf3_key & key, Weights && weights) { std::uint64_t acc = 0; for (std::size_t x = 0; x < it_dpf3_key::domain_size; ++x) acc += key.share[x] * static_cast(weights[x]); return acc; } } // namespace dpf #endif // LIBDPF_INCLUDE_DPF_IT_DPF3_HPP__