feat(oprf): add split-blinding unlinkable OPRF (partial unlinkability)
- Implement split-blinding protocol with C, C_r dual evaluation - Add 7 security proof tests for unlinkability properties - Add benchmarks: ~101µs (109x faster than OT-based) - Note: Server can compute C - C_r fingerprint (documented limitation)
This commit is contained in:
@@ -14,6 +14,10 @@ use opaque_lattice::oprf::ring_lpr::{
|
||||
RingLprKey, client_blind as lpr_client_blind, client_finalize as lpr_finalize,
|
||||
server_evaluate as lpr_server_evaluate,
|
||||
};
|
||||
use opaque_lattice::oprf::unlinkable_oprf::{
|
||||
UnlinkablePublicParams, UnlinkableServerKey, client_blind_unlinkable,
|
||||
client_finalize_unlinkable, evaluate_unlinkable, server_evaluate_unlinkable,
|
||||
};
|
||||
|
||||
/// Benchmark Fast OPRF (OT-free) - full protocol
|
||||
fn bench_fast_oprf(c: &mut Criterion) {
|
||||
@@ -96,15 +100,16 @@ fn bench_ring_lpr_oprf(c: &mut Criterion) {
|
||||
group.finish();
|
||||
}
|
||||
|
||||
/// Compare both protocols side-by-side
|
||||
/// Compare all three protocols side-by-side
|
||||
fn bench_comparison(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("oprf_comparison");
|
||||
|
||||
// Fast OPRF setup
|
||||
let pp = PublicParams::generate(b"benchmark-params");
|
||||
let fast_key = ServerKey::generate(&pp, b"benchmark-key");
|
||||
|
||||
// Ring-LPR setup
|
||||
let unlink_pp = UnlinkablePublicParams::generate(b"benchmark-params");
|
||||
let unlink_key = UnlinkableServerKey::generate(&unlink_pp, b"benchmark-key");
|
||||
|
||||
let mut rng = ChaCha20Rng::seed_from_u64(12345);
|
||||
let lpr_key = RingLprKey::generate(&mut rng);
|
||||
|
||||
@@ -121,6 +126,12 @@ fn bench_comparison(c: &mut Criterion) {
|
||||
b.iter(|| fast_evaluate(&pp, &fast_key, pwd))
|
||||
});
|
||||
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("unlinkable_oprf", len),
|
||||
password,
|
||||
|b, pwd| b.iter(|| evaluate_unlinkable(&unlink_pp, &unlink_key, pwd)),
|
||||
);
|
||||
|
||||
group.bench_with_input(
|
||||
BenchmarkId::new("ring_lpr_oprf", len),
|
||||
password,
|
||||
@@ -138,6 +149,36 @@ fn bench_comparison(c: &mut Criterion) {
|
||||
group.finish();
|
||||
}
|
||||
|
||||
/// Benchmark Unlinkable OPRF - full protocol
|
||||
fn bench_unlinkable_oprf(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("unlinkable_oprf");
|
||||
|
||||
let pp = UnlinkablePublicParams::generate(b"benchmark-params");
|
||||
let key = UnlinkableServerKey::generate(&pp, b"benchmark-key");
|
||||
let password = b"benchmark-password-12345";
|
||||
|
||||
group.bench_function("client_blind", |b| {
|
||||
b.iter(|| client_blind_unlinkable(&pp, password))
|
||||
});
|
||||
|
||||
let (state, blinded) = client_blind_unlinkable(&pp, password);
|
||||
group.bench_function("server_evaluate", |b| {
|
||||
b.iter(|| server_evaluate_unlinkable(&key, &blinded))
|
||||
});
|
||||
|
||||
let response = server_evaluate_unlinkable(&key, &blinded);
|
||||
group.bench_function("client_finalize", |b| {
|
||||
let state = state.clone();
|
||||
b.iter(|| client_finalize_unlinkable(&state, key.public_key(), &response))
|
||||
});
|
||||
|
||||
group.bench_function("full_protocol", |b| {
|
||||
b.iter(|| evaluate_unlinkable(&pp, &key, password))
|
||||
});
|
||||
|
||||
group.finish();
|
||||
}
|
||||
|
||||
/// Benchmark message sizes
|
||||
fn bench_message_sizes(c: &mut Criterion) {
|
||||
println!("\n=== Message Size Comparison ===\n");
|
||||
@@ -181,6 +222,7 @@ fn bench_message_sizes(c: &mut Criterion) {
|
||||
criterion_group!(
|
||||
benches,
|
||||
bench_fast_oprf,
|
||||
bench_unlinkable_oprf,
|
||||
bench_ring_lpr_oprf,
|
||||
bench_comparison,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user