This commit is contained in:
Sarah Jamie Lewis 2021-01-31 15:42:37 -08:00
parent 71c3db28d6
commit a17f5ffe0d
4 changed files with 96 additions and 15 deletions

View File

@ -27,7 +27,7 @@ Which brings us onto:
### Differential Attacks
Any kind of differential attacks break this scheme, even for a small number of messages i.e. if you learn (through
any means, that a specific set of messages are all likely for 1 party, you can diff them against all other parties keys and
any means) that a specific set of messages are all likely for 1 party, you can diff them against all other parties keys and
very quickly isolate the intended recipient - in simulations of 100-1000 parties it can take as little as 3 messages - even
with everyone selecting fairly high false positive rates.
@ -40,7 +40,7 @@ To what extent you can actually account for this in your application is an open
### Should Senders use an anonymous communication network?
If differential attacks are likely e.g. few parties download everything and
multiple messages are expect to originate from a sender to a receiver or there
multiple messages are expected to originate from a sender to a receiver or there
is other information that might otherwise link a set of messages to a receiver then you may want to consider how
to remove that context.

View File

@ -1,7 +1,7 @@
[package]
name = "fuzzytags"
description = "a probabilistic cryptographic structure for metadata resistant tagging"
version = "0.1.3"
version = "0.1.4"
repository = "https://git.openprivacy.ca/openprivacy/fuzzytags"
authors = ["Sarah Jamie Lewis <sarah@openprivacy.ca>"]
edition = "2018"

View File

@ -68,8 +68,9 @@ provided them (depending on the efficiency of the decryption method).
Generate a key pair:
let gamma = 3;
let key = FuzzyTagKeyPair::generate(gamma);
use fuzzytags::FuzzyTagKeyPair;
let gamma = 24;
let keypair = FuzzyTagKeyPair::generate(gamma);
`key.public_key` can be given to parties who you want to be able to communicate with you over a specific anonymous
messaging service / privacy-preserving application.
@ -77,29 +78,54 @@ messaging service / privacy-preserving application.
`key.detection_key` can be given to untrusted _adversarial_ servers.
`gamma` is security property (_γ_) in the system. For a given gamma, a tag generated for a specific public key will
validate against a random public key with a maximum probability of 2^-gamma.
validate against a random public key with a maximum probability of _2^-gamma_.
## Generating Tags
Once in possession of a public key, a party in a metadata resistant app can use it to generate tags:
let tag = public_key.generate_tag();
use fuzzytags::FuzzyTagKeyPair;
let gamma = 24;
let keypair = FuzzyTagKeyPair::generate(gamma);
let public_key = keypair.public_key.clone();
// Give public key to a another party...
// and then they can do...
let tag = public_key.generate_tag();
These tags can then be attached to a message in a metadata resistant system.
## Testing Tags
First it is necessary to extract a detection key for a given false positive probability 0 <= 2^-n <= 2^-γ.
First it is necessary to extract a detection key for a given false positive probability _0 <= 2^-n <= 2^-γ_.
This extracted key can then be given to an adversarial server. The server can then test a given tag against the detection key e.g.:
let detection_key = key.extract(5);
if detection_key.test_tag(tag) {
// the message attached to this tag *might* be for the party associated with the detection key
} else {
// the message attached to this tag is definitely *not* for the party associated with the detection key.
}
use fuzzytags::FuzzyTagKeyPair;
let gamma = 24;
let keypair = FuzzyTagKeyPair::generate(gamma);
let public_key = keypair.public_key.clone();
// extract a detection key
let detection_key = keypair.extract(5);
// Give public key to a another party...
// and then they can do...
let tag = public_key.generate_tag();
// The server can now do this:
if detection_key.test_tag(&tag) {
// the message attached to this tag *might* be for the party associated with the detection key
} else {
// the message attached to this tag is definitely *not* for the party associated with the detection key.
}
## Benchmarks
We use [criterion](https://crates.io/crates/criterion) for benchmarking, and benchmarks can run using `cargo bench`
Results will be in `target/criterion/report/index.html`.
## Integrating fuzzytags
For more guidance on integrating fuzzytags into a privacy preserving application see [documentation](https://docs.rs/fuzzytags/#integrating-fuzzytags)

View File

@ -31,10 +31,17 @@ pub struct FuzzyTag {
/// The complete secret key. Can't directly be used for testing. Instead you will need to generate
/// a FuzzyDetectionKey using extract
#[derive(Debug, Serialize, Deserialize)]
pub struct FuzzySecretKey(Vec<Scalar>);
impl FuzzySecretKey {
/// extract a detection key for a given false positive (p = 2^-n)
/// Example:
/// ```
/// use fuzzytags::{FuzzyTagKeyPair};
/// let keypair = FuzzyTagKeyPair::generate(24);
/// let detection_key = keypair.extract(2);
/// ```
pub fn extract(&self, n: usize) -> FuzzyDetectionKey {
let parts = self.0.iter().take(n).cloned().collect();
FuzzyDetectionKey { 0: parts }
@ -47,13 +54,41 @@ impl FuzzySecretKey {
pub struct FuzzyDetectionKey(Vec<Scalar>);
impl FuzzyDetectionKey {
/// calculate the ideal false positive rate of this detection key
/// ```
/// use fuzzytags::FuzzyTagKeyPair;
/// let gamma = 24;
/// let keypair = FuzzyTagKeyPair::generate(gamma);
/// let public_key = keypair.public_key.clone();
/// // extract a detection key
/// let detection_key = keypair.extract(5);
/// detection_key.false_positive_probability();
/// ```
pub fn false_positive_probability(&self) -> f64 {
(2.0_f64).powi(0 - (self.0.len() as i32))
}
/// returns true if the tag was intended for this key
/// Example:
/// ```
/// use fuzzytags::FuzzyTagKeyPair;
/// let gamma = 24;
/// let keypair = FuzzyTagKeyPair::generate(gamma);
/// let public_key = keypair.public_key.clone();
/// // extract a detection key
/// let detection_key = keypair.extract(5);
///
/// // Give public key to a another party...
/// // and then they can do...
/// let tag = public_key.generate_tag();
///
/// // The server can now do this:
/// if detection_key.test_tag(&tag) {
/// // the message attached to this tag *might* be for the party associated with the detection key
/// } else {
/// // the message attached to this tag is definitely *not* for the party associated with the detection key.
/// }
/// ```
pub fn test_tag(&self, tag: &FuzzyTag) -> bool {
let m = FuzzyTagKeyPair::g(tag.u, &tag.ciphertexts);
@ -94,10 +129,18 @@ impl FuzzyDetectionKey {
}
/// A public identity that others can create tags for.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FuzzyPublicKey(Vec<RistrettoPoint>);
impl FuzzyPublicKey {
/// generate a new tag for this public key
/// Example:
/// ```
/// use fuzzytags::{FuzzyTagKeyPair};
/// let keypair = FuzzyTagKeyPair::generate(24);
/// let public_key = keypair.public_key.clone(); // give this to a sender
/// let tag = public_key.generate_tag();
/// ```
pub fn generate_tag(&self) -> FuzzyTag {
let mut rng = OsRng::default();
let g = RISTRETTO_BASEPOINT_POINT;
@ -152,6 +195,7 @@ impl Display for FuzzyTag {
}
/// An identity keypair for generating and validating fuzzy meta tags.
#[derive(Debug, Serialize, Deserialize)]
pub struct FuzzyTagKeyPair {
/// the detection key - this can be given to adversarial servers to help probabilistically
/// filter messages (with a false-positive rate derived from γ and a 0% false negative rate)
@ -164,6 +208,11 @@ impl FuzzyTagKeyPair {
/// Generate a new Key Pair given a security parameter `gamma`. Tags generated for a given
/// `FuzzyPublicKey::flag` will pass the `FuzzyDetectionKey::test` for other public
/// keys with probability $ 2 ^ -8 $
/// Example:
/// ```
/// use fuzzytags::{FuzzyTagKeyPair};
/// let keypair = FuzzyTagKeyPair::generate(5);
/// ```
pub fn generate(gamma: usize) -> FuzzyTagKeyPair {
let mut rng = OsRng::default();
let g = RISTRETTO_BASEPOINT_POINT;
@ -183,6 +232,12 @@ impl FuzzyTagKeyPair {
/// extract a detection key for a given false positive (p = 2^-n)
/// a facade for an extraction of the encapsulated secret key
/// Example:
/// ```
/// use fuzzytags::{FuzzyTagKeyPair};
/// let keypair = FuzzyTagKeyPair::generate(24);
/// let detection_key = keypair.extract(2);
/// ```
pub fn extract(&self, n: usize) -> FuzzyDetectionKey {
self.secret_key.extract(n)
}