libdpf/examples/applications/express.cpp

85 lines
2.5 KiB
C++
Raw Normal View History

#include <cstddef>
#include <cstdint>
#include <iostream>
#include <vector>
#include "dpf.hpp"
#include "dpf/app_flow.hpp"
#include "dpf/app_plans.hpp"
// Express, the mailbox write (Eskandarian, Corrigan-Gibbs, Zaharia, Boneh,
// USENIX Security 2021 §3.1). Two servers hold XOR shares of every mailbox
// row. The client sends one `blob` DPF key each. Each server adds its
// expansion into its share and folds the one-hot audit in the same walk.
//
// c++ -std=c++17 -march=native -I include -I thirdparty \
// examples/applications/express.cpp
namespace
{
constexpr std::size_t nboxes = 256;
constexpr std::size_t row_bytes = 100;
using row_t = dpf::blob<row_bytes>;
} // namespace
int main()
{
constexpr std::uint8_t address = 9;
row_t message{};
for (std::size_t i = 0; i < row_bytes; ++i)
message.bytes[i] = static_cast<unsigned char>(i + 1);
auto [k0, k1] = dpf::make_dpf(address, message);
std::vector<row_t> box0(nboxes), box1(nboxes);
// One-pass caller fold: count how many non-zero shares each server sees.
std::size_t hot0 = 0, hot1 = 0;
dpf::eval_full_add_into(box0, k0, [&](std::size_t, const row_t & s) {
if (s != row_t{})
++hot0;
});
dpf::eval_full_add_into(box1, k1, [&](std::size_t, const row_t & s) {
if (s != row_t{})
++hot1;
});
(void)hot0;
(void)hot1;
if ((box0[address] ^ box1[address]) != message)
{
std::cerr << "express mailbox\n";
return 1;
}
if ((box0[0] ^ box1[0]) != row_t{})
{
std::cerr << "express neighbor\n";
return 1;
}
// fp61 one-hot audit on a parallel extractable key (same walk shape).
auto [a0, a1] = dpf::make_dpf(address, dpf::fp61{1}, dpf::extractable{});
std::vector<dpf::fp61> challenge(nboxes);
for (std::size_t i = 0; i < nboxes; ++i)
challenge[i] = dpf::fp61{static_cast<std::uint64_t>(i + 1)};
std::vector<dpf::fp61> audit0(nboxes), audit1(nboxes);
dpf::sketch_share s0{}, s1{};
dpf::eval_full_add_into(audit0, a0, dpf::sketch(s0, challenge));
dpf::eval_full_add_into(audit1, a1, dpf::sketch(s1, challenge));
if (!dpf::sketch_verify(s0, s1))
{
std::cerr << "express audit\n";
return 1;
}
{
if (int rc = dpf::app::run_measured("express",
dpf::protocol::mailbox_write_fused_plan(0, 8), 8))
return rc;
}
std::cout << static_cast<unsigned>(message.bytes[0]) << "\n";
return 0;
}