From c1ce746da8bd979ccd84845cc2ca4ad32ffaa0f4 Mon Sep 17 00:00:00 2001 From: Sarah Jamie Lewis Date: Tue, 2 Feb 2021 16:19:20 -0800 Subject: [PATCH] Adding entangled feature --- Cargo.toml | 5 ++++- README.md | 16 ++++++++++++++++ src/lib.rs | 26 +++++++++++++++++++++++--- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fb5c361..cd10165 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ curve25519-dalek = {version="3.0.0", features=["serde"]} sha3 = "0.9.1" bit-vec = {version="0.6.3", features=["serde"]} serde = {version="1.0.123", features=["derive"]} -rayon = "1.5.0" +rayon = {version="1.5.0", optional = true} [dev-dependencies] criterion = {version="0.3", features=["html_reports"]} @@ -26,3 +26,6 @@ serde_json = "1.0.61" name = "fuzzy_tags_benches" harness = false +[features] +entangled = ["rayon"] + diff --git a/README.md b/README.md index e780914..36f0408 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,22 @@ This extracted key can then be given to an adversarial server. The server can th // the message attached to this tag is definitely *not* for the party associated with the detection key. } +## Entangled Tags + +When enabled with the `entangled` feature the `FuzzyPublicKey::generate_entangled_tag` function is available. This +allows you to generate tags that will validate against **multiple** detection keys from **distinct public keys** and +opens up applications like **multiple broadcast** and **deniable sending**. + + #[cfg(feature = "entangled")] + use fuzzytags::{FuzzySecretKey, FuzzyPublicKey}; + let secret_key_1 = FuzzySecretKey::generate(24); + let secret_key_2 = FuzzySecretKey::generate(24); + let public_key_1 = secret_key_1.public_key(); // give this to a sender + let public_key_2 = secret_key_2.public_key(); // give this to a sender + // Will validate for detection keys derived from both secret_key_1 and secret_key_2 up + // to n=8 + let tag = FuzzyPublicKey::generate_entangled_tag(vec![public_key_1,public_key_2], 8); + ## Benchmarks We use [criterion](https://crates.io/crates/criterion) for benchmarking, and benchmarks can run using `cargo bench` diff --git a/src/lib.rs b/src/lib.rs index 08fb06c..2d7a1cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,16 +10,21 @@ use curve25519_dalek::ristretto::RistrettoPoint; use curve25519_dalek::scalar::Scalar; use curve25519_dalek::traits::MultiscalarMul; use rand::rngs::OsRng; -use rayon::iter::ParallelIterator; -use rayon::prelude::IntoParallelIterator; use serde::Deserialize; use serde::Serialize; use sha3::Sha3_512; use std::fmt; use std::fmt::{Display, Formatter}; use std::ops::{Mul, Sub}; + +#[cfg(feature = "entangled")] use std::sync::Arc; +#[cfg(feature = "entangled")] +use rayon::iter::ParallelIterator; +#[cfg(feature = "entangled")] +use rayon::prelude::IntoParallelIterator; + /// 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 test with probability `gamma` related to the security parameter of the system. @@ -285,9 +290,21 @@ impl FuzzyPublicKey { return FuzzyTag { u, y, ciphertexts }; } + #[cfg(feature = "entangled")] /// WARNING: if you pass in a large length into this function it will take a long time! /// This begins a very slow, but ,parallel search for a tag that will validate of the given /// public keys up to a given false positive rate 2^-1 + /// Example: + /// ``` + /// use fuzzytags::{FuzzySecretKey, FuzzyPublicKey}; + /// let secret_key_1 = FuzzySecretKey::generate(24); + /// let secret_key_2 = FuzzySecretKey::generate(24); + /// let public_key_1 = secret_key_1.public_key(); // give this to a sender + /// let public_key_2 = secret_key_2.public_key(); // give this to a sender + /// // Will validate for detection keys derived from both secret_key_1 and secret_key_2 up + /// // to n=8 + /// let tag = FuzzyPublicKey::generate_entangled_tag(vec![public_key_1,public_key_2], 8); + /// ``` pub fn generate_entangled_tag(public_keys: Vec, length: usize) -> FuzzyTag { let arc_public_keys = Arc::new(public_keys); loop { @@ -303,6 +320,7 @@ impl FuzzyPublicKey { } } + #[cfg(feature = "entangled")] fn try_entangled_tag(public_keys: Arc>, length: usize) -> Result { let mut rng = OsRng::default(); let g = RISTRETTO_BASEPOINT_POINT; @@ -384,7 +402,7 @@ impl FuzzyPublicKey { #[cfg(test)] mod tests { - use crate::{FuzzyPublicKey, FuzzySecretKey}; + use crate::FuzzySecretKey; #[test] fn test_serialization() { @@ -396,7 +414,9 @@ mod tests { } #[test] + #[cfg(feature = "entangled")] fn test_multiple() { + use crate::FuzzyPublicKey; let secret_keys: Vec = (0..3).map(|_x| FuzzySecretKey::generate(24)).collect(); let public_keys: Vec = 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