doctests
This commit is contained in:
parent
71c3db28d6
commit
a17f5ffe0d
|
@ -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.
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
|
48
README.md
48
README.md
|
@ -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)
|
||||
|
||||
|
|
57
src/lib.rs
57
src/lib.rs
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue