Move entangled tag generation over to brute-force library
This commit is contained in:
parent
b6338e11e5
commit
1adfe996a6
|
@ -1,7 +1,7 @@
|
||||||
[package]
|
[package]
|
||||||
name = "fuzzytags"
|
name = "fuzzytags"
|
||||||
description = "a probabilistic cryptographic structure for metadata resistant tagging"
|
description = "a probabilistic cryptographic structure for metadata resistant tagging"
|
||||||
version = "0.2.3"
|
version = "0.3.0"
|
||||||
repository = "https://git.openprivacy.ca/openprivacy/fuzzytags"
|
repository = "https://git.openprivacy.ca/openprivacy/fuzzytags"
|
||||||
authors = ["Sarah Jamie Lewis <sarah@openprivacy.ca>"]
|
authors = ["Sarah Jamie Lewis <sarah@openprivacy.ca>"]
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
@ -17,7 +17,7 @@ curve25519-dalek = {version="3.0.0", features=["serde"]}
|
||||||
sha3 = "0.9.1"
|
sha3 = "0.9.1"
|
||||||
bit-vec = {version="0.6.3", features=["serde"]}
|
bit-vec = {version="0.6.3", features=["serde"]}
|
||||||
serde = {version="1.0.123", features=["derive"]}
|
serde = {version="1.0.123", features=["derive"]}
|
||||||
rayon = {version="1.5.0", optional = true}
|
brute-force = {version="0.1.0", features=["curve25519"], optional=true}
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
criterion = {version="0.3", features=["html_reports"]}
|
criterion = {version="0.3", features=["html_reports"]}
|
||||||
|
@ -28,5 +28,5 @@ name = "fuzzy_tags_benches"
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
entangled = ["rayon"]
|
entangled = ["brute-force"]
|
||||||
|
|
||||||
|
|
79
src/lib.rs
79
src/lib.rs
|
@ -18,11 +18,9 @@ use std::fmt::{Display, Formatter};
|
||||||
use std::ops::{Mul, Sub};
|
use std::ops::{Mul, Sub};
|
||||||
|
|
||||||
#[cfg(feature = "entangled")]
|
#[cfg(feature = "entangled")]
|
||||||
use rayon::iter::ParallelIterator;
|
use brute_force::adaptors;
|
||||||
#[cfg(feature = "entangled")]
|
#[cfg(feature = "entangled")]
|
||||||
use rayon::prelude::IntoParallelIterator;
|
use brute_force::brute_force;
|
||||||
#[cfg(feature = "entangled")]
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
/// A tag is a probabilistic cryptographic structure. When constructed for a given `FuzzyPublicKey`
|
/// A tag is a probabilistic cryptographic structure. When constructed for a given `FuzzyPublicKey`
|
||||||
/// it will pass the `FuzzyDetectionKey::test` 100% of the time. For other public keys
|
/// it will pass the `FuzzyDetectionKey::test` 100% of the time. For other public keys
|
||||||
|
@ -313,38 +311,12 @@ impl FuzzyPublicKey {
|
||||||
/// let tag = FuzzyPublicKey::generate_entangled_tag(vec![public_key_1,public_key_2], 8);
|
/// let tag = FuzzyPublicKey::generate_entangled_tag(vec![public_key_1,public_key_2], 8);
|
||||||
/// ```
|
/// ```
|
||||||
pub fn generate_entangled_tag(public_keys: Vec<FuzzyPublicKey>, length: usize) -> FuzzyTag {
|
pub fn generate_entangled_tag(public_keys: Vec<FuzzyPublicKey>, length: usize) -> FuzzyTag {
|
||||||
let arc_public_keys = Arc::new(public_keys);
|
|
||||||
loop {
|
|
||||||
let results: Vec<FuzzyTag> = (0..8)
|
|
||||||
.into_par_iter()
|
|
||||||
.map(|_x| FuzzyPublicKey::try_entangled_tag(arc_public_keys.clone(), length))
|
|
||||||
.filter_map(|x| x.ok())
|
|
||||||
.collect();
|
|
||||||
if results.is_empty() == false {
|
|
||||||
return results[0].clone();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "entangled")]
|
|
||||||
fn try_entangled_tag(public_keys: Arc<Vec<FuzzyPublicKey>>, length: usize) -> Result<FuzzyTag, ()> {
|
|
||||||
let mut rng = OsRng::default();
|
let mut rng = OsRng::default();
|
||||||
let g = RISTRETTO_BASEPOINT_POINT;
|
let g = RISTRETTO_BASEPOINT_POINT;
|
||||||
|
|
||||||
// generate some random points...
|
// generate some random points...
|
||||||
let r = Scalar::random(&mut rng);
|
let r = Scalar::random(&mut rng);
|
||||||
let u = g.mul(r);
|
let u = g.mul(r);
|
||||||
|
|
||||||
// Set z to zero...
|
|
||||||
let mut z = Scalar::zero();
|
|
||||||
|
|
||||||
// construct the ciphertext portion of the tag
|
|
||||||
let mut ciphertexts = BitVec::new();
|
|
||||||
|
|
||||||
// Keep track of how many attempts and whether we have succeeded...
|
|
||||||
let mut attempts = 0;
|
|
||||||
let mut entangled = false;
|
|
||||||
|
|
||||||
// Compute and cache some public points that we will be using over and over again
|
// Compute and cache some public points that we will be using over and over again
|
||||||
let mut public_key_precomputes = vec![];
|
let mut public_key_precomputes = vec![];
|
||||||
for public_key in public_keys.iter() {
|
for public_key in public_keys.iter() {
|
||||||
|
@ -355,46 +327,37 @@ impl FuzzyPublicKey {
|
||||||
public_key_precomputes.push(precompute);
|
public_key_precomputes.push(precompute);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try a 1000 different options and hope maybe one of them is the magic number...
|
let config = brute_force::Config::default();
|
||||||
while !entangled && attempts < 1000 {
|
let f = |z: &Scalar| {
|
||||||
attempts += 1;
|
|
||||||
ciphertexts = BitVec::new();
|
|
||||||
z = Scalar::random(&mut rng);
|
|
||||||
let w = g.mul(z);
|
let w = g.mul(z);
|
||||||
entangled = true;
|
let mut key = vec![];
|
||||||
for (i, precompute) in public_key_precomputes[0].iter().enumerate() {
|
for (i, precompute) in public_key_precomputes[0].iter().enumerate() {
|
||||||
let mut same = true;
|
|
||||||
let k_i = FuzzySecretKey::h(u, *precompute, w);
|
let k_i = FuzzySecretKey::h(u, *precompute, w);
|
||||||
|
|
||||||
if i < length {
|
if i < length {
|
||||||
for precompute in public_key_precomputes.iter().skip(1) {
|
for precompute in public_key_precomputes.iter().skip(1) {
|
||||||
let n_k_i = FuzzySecretKey::h(u, precompute[i], w);
|
let n_k_i = FuzzySecretKey::h(u, precompute[i], w);
|
||||||
if k_i != n_k_i {
|
if k_i != n_k_i {
|
||||||
same = false;
|
return None;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !same {
|
key.push(k_i)
|
||||||
entangled = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate the tag
|
||||||
|
let mut ciphertexts = BitVec::new();
|
||||||
|
for k_i in key.iter() {
|
||||||
// encrypt a plaintext of all 1's
|
// encrypt a plaintext of all 1's
|
||||||
let c_i = k_i ^ 0x01;
|
let c_i = k_i ^ 0x01;
|
||||||
ciphertexts.push(c_i == 0x01);
|
ciphertexts.push(c_i == 0x01);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If we are not entangled then at this point we return an error
|
// This is the same as generate_tag, kept separate to avoid over-decomposition
|
||||||
if entangled == false {
|
let m = FuzzySecretKey::g(u, &ciphertexts);
|
||||||
return Err(());
|
let y = r.invert().mul(z.sub(m));
|
||||||
}
|
return Some(FuzzyTag { u, y, ciphertexts });
|
||||||
|
};
|
||||||
// This is the same as generate_tag, kept separate to avoid over-decomposition
|
brute_force(config, adaptors::auto_advance(f))
|
||||||
let m = FuzzySecretKey::g(u, &ciphertexts);
|
|
||||||
let y = r.invert().mul(z.sub(m));
|
|
||||||
|
|
||||||
return Ok(FuzzyTag { u, y, ciphertexts });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -418,13 +381,13 @@ mod tests {
|
||||||
#[cfg(feature = "entangled")]
|
#[cfg(feature = "entangled")]
|
||||||
fn test_multiple() {
|
fn test_multiple() {
|
||||||
use crate::FuzzyPublicKey;
|
use crate::FuzzyPublicKey;
|
||||||
let secret_keys: Vec<FuzzySecretKey> = (0..3).map(|_x| FuzzySecretKey::generate(24)).collect();
|
let secret_keys: Vec<FuzzySecretKey> = (0..2).map(|_x| FuzzySecretKey::generate(24)).collect();
|
||||||
let public_keys: Vec<FuzzyPublicKey> = secret_keys.iter().map(|x| x.public_key()).collect();
|
let public_keys: Vec<FuzzyPublicKey> = secret_keys.iter().map(|x| x.public_key()).collect();
|
||||||
// it takes ~15 minutes on a standard desktop to find a length=24 match for 2 parties, so for testing let's keep things light
|
// it takes ~15 minutes on a standard desktop to find a length=24 match for 2 parties, so for testing let's keep things light
|
||||||
let entangled_tag = FuzzyPublicKey::generate_entangled_tag(public_keys, 6);
|
let entangled_tag = FuzzyPublicKey::generate_entangled_tag(public_keys, 16);
|
||||||
println!("{}", entangled_tag);
|
println!("{}", entangled_tag);
|
||||||
for secret_key in secret_keys.iter() {
|
for secret_key in secret_keys.iter() {
|
||||||
let detection_key = secret_key.extract(6);
|
let detection_key = secret_key.extract(16);
|
||||||
assert!(detection_key.test_tag(&entangled_tag));
|
assert!(detection_key.test_tag(&entangled_tag));
|
||||||
println!("{}", detection_key);
|
println!("{}", detection_key);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue