libdpf/examples/applications/psi.cpp

76 lines
2.1 KiB
C++
Raw Permalink Normal View History

#include <cstdint>
#include <cstring>
#include <iostream>
#include <vector>
#include "dpf.hpp"
#include "dpf/app_flow.hpp"
#include "dpf/app_plans.hpp"
// Private set intersection, the DPF step (Kolesnikov, Kumaresan, Rosulek,
// and Trieu, CCS 2016). The sender keeps a puncturable-PRF master. Each
// receiver element is a puncture; the servers evaluate the punctured key
// and test whether the tag sits in the sender's image. No full-domain table.
//
// c++ -std=c++17 -march=native -I include -I thirdparty \
// examples/applications/psi.cpp
namespace
{
using domain_t = std::uint8_t;
bool blocks_eq(simde__m128i a, simde__m128i b)
{
return std::memcmp(&a, &b, sizeof(a)) == 0;
}
bool in_image(simde__m128i tag, const std::vector<simde__m128i> & image)
{
for (auto v : image)
if (blocks_eq(v, tag))
return true;
return false;
}
} // namespace
int main()
{
auto master = dpf::make_pprf_master<domain_t>();
const domain_t sender[] = {4, 10, 42};
const domain_t receiver[] = {42, 7};
std::vector<simde__m128i> image;
for (auto x : sender)
image.push_back(dpf::pprf_eval(master, x));
auto punctured_hit = dpf::puncture(master, receiver[0]);
auto punctured_miss = dpf::puncture(master, receiver[1]);
// Off-path points agree with the master; the programmed leaf at alpha
// matches the master leaf (sender who keeps the master set it).
const auto hit = dpf::pprf_eval(punctured_hit, receiver[0]);
const auto miss_off = dpf::pprf_eval(punctured_miss, domain_t{0});
const auto master_miss_off = dpf::pprf_eval(master, domain_t{0});
if (!blocks_eq(hit, dpf::pprf_eval(master, receiver[0]))
|| !in_image(hit, image)
|| in_image(dpf::pprf_eval(master, receiver[1]), image)
|| !blocks_eq(miss_off, master_miss_off))
{
std::cerr << "psi\n";
return 1;
}
{
if (int rc = dpf::app::run_measured("psi",
dpf::protocol::psi_cuckoo_plan(0, {0, 1, 0}), 9))
return rc;
}
std::cout << "1\n";
return 0;
}