Settle on a name
This commit is contained in:
parent
0f9720a215
commit
0040e0c905
|
@ -1,5 +1,5 @@
|
|||
[package]
|
||||
name = "fuzzymetatag"
|
||||
name = "fuzzytags"
|
||||
version = "0.1.0"
|
||||
authors = ["Sarah Jamie Lewis <sarah@openprivacy.ca>"]
|
||||
edition = "2018"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# fuzzymetatag
|
||||
# FuzzyTags
|
||||
|
||||
Anonymous messaging systems (and other privacy-preserving applications) often require a mechanism for one party
|
||||
to learn that another party has messaged them.
|
||||
|
@ -8,7 +8,7 @@ Many schemes rely on a bandwidth-intensive "download everything and attempt-decr
|
|||
|
||||
It would be awesome if we could get an untrusted server to do the work for us without compromising metadata-resistance!
|
||||
|
||||
fuzzymetatag is a probabilistic cryptographic structure to do just that! Specifically it provides the following
|
||||
**fuzzytags** is a probabilistic cryptographic structure to do just that! Specifically it provides the following
|
||||
properties:
|
||||
|
||||
* Correctness: Valid tags constructed for a specific public key will always validate when tested using the detection key
|
||||
|
@ -37,7 +37,7 @@ increases false positives.
|
|||
Generate a key pair:
|
||||
|
||||
let gamma = 3;
|
||||
let key = FuzzyMetaTagKeyPair::generate(gamma);
|
||||
let key = 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.
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
use fuzzymetatag::FuzzyMetaTagKeyPair;
|
||||
use fuzzytags::FuzzyTagKeyPair;
|
||||
use std::time::Duration;
|
||||
|
||||
fn benchmark_generate_tag(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("generate_tags");
|
||||
group.measurement_time(Duration::new(10, 0));
|
||||
let key = FuzzyMetaTagKeyPair::generate(24);
|
||||
let key = FuzzyTagKeyPair::generate(24);
|
||||
for p in [5, 10, 15].iter() {
|
||||
group.bench_with_input(BenchmarkId::from_parameter(p), p, |b, _gamma| b.iter(|| key.public_key.generate_tag()));
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ fn benchmark_generate_tag(c: &mut Criterion) {
|
|||
fn benchmark_test_tag(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("test_tags");
|
||||
group.measurement_time(Duration::new(10, 0));
|
||||
let key = FuzzyMetaTagKeyPair::generate(24);
|
||||
let key = FuzzyTagKeyPair::generate(24);
|
||||
for p in [5, 10, 15].iter() {
|
||||
let tag = key.public_key.generate_tag();
|
||||
let detection_key = key.extract(*p);
|
||||
|
|
72
src/lib.rs
72
src/lib.rs
|
@ -14,41 +14,41 @@ use std::fmt;
|
|||
use std::fmt::{Display, Formatter};
|
||||
use std::ops::{Add, Mul, Sub};
|
||||
|
||||
/// A tag is a probabilistic cryptographic structure. When constructed for a given `FuzzyMetaPublicKey`
|
||||
/// it will pass the `FuzzyMetaDetectionKey::test` 100% of the time. For other public keys
|
||||
/// 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.
|
||||
/// This system provides the following security properties:
|
||||
/// * Correctness: Valid tags constructed for a specific public key will always validate when tested using the detection key
|
||||
/// * Fuzziness: Invalid tags will produce false positives with probability _p_ related to the security property (_γ_)
|
||||
/// * Security: An adversarial server with access to the detection key is unable to distinguish false positives from true positives. (Detection Ambiguity)
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct FuzzyMetaTag {
|
||||
pub struct FuzzyTag {
|
||||
u: RistrettoPoint,
|
||||
y: Scalar,
|
||||
ciphertexts: BitVec,
|
||||
}
|
||||
|
||||
/// The complete secret key. Can't directly be used for testing. Instead you will need to generate
|
||||
/// a FuzzyMetaDetectionKey using extract
|
||||
pub struct FuzzyMetaSecretKey(Vec<Scalar>);
|
||||
/// a FuzzyDetectionKey using extract
|
||||
pub struct FuzzySecretKey(Vec<Scalar>);
|
||||
|
||||
impl FuzzyMetaSecretKey {
|
||||
impl FuzzySecretKey {
|
||||
/// extract a detection key for a given false positive (p = 2^-n)
|
||||
pub fn extract(&self, n: usize) -> FuzzyMetaDetectionKey {
|
||||
pub fn extract(&self, n: usize) -> FuzzyDetectionKey {
|
||||
let parts = self.0.iter().take(n).cloned().collect();
|
||||
FuzzyMetaDetectionKey { 0: parts }
|
||||
FuzzyDetectionKey { 0: parts }
|
||||
}
|
||||
}
|
||||
|
||||
/// A collection of "secret" data that can be used to determine if a `FuzzyMetaTag` was intended for
|
||||
/// A collection of "secret" data that can be used to determine if a `FuzzyTag` was intended for
|
||||
/// the derived public key with probability p
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct FuzzyMetaDetectionKey(Vec<Scalar>);
|
||||
pub struct FuzzyDetectionKey(Vec<Scalar>);
|
||||
|
||||
impl FuzzyMetaDetectionKey {
|
||||
impl FuzzyDetectionKey {
|
||||
/// returns true if the tag was intended for this key
|
||||
pub fn test_tag(&self, tag: &FuzzyMetaTag) -> bool {
|
||||
let m = FuzzyMetaTagKeyPair::g(tag.u, &tag.ciphertexts);
|
||||
pub fn test_tag(&self, tag: &FuzzyTag) -> bool {
|
||||
let m = FuzzyTagKeyPair::g(tag.u, &tag.ciphertexts);
|
||||
|
||||
let g = RISTRETTO_BASEPOINT_POINT;
|
||||
|
||||
|
@ -66,7 +66,7 @@ impl FuzzyMetaDetectionKey {
|
|||
let mut result = true;
|
||||
for (i, x_i) in self.0.iter().enumerate() {
|
||||
// re-derive the key from the tag
|
||||
let k_i = FuzzyMetaTagKeyPair::h(tag.u, tag.u.mul(x_i), w);
|
||||
let k_i = FuzzyTagKeyPair::h(tag.u, tag.u.mul(x_i), w);
|
||||
|
||||
// calculate the "original" plaintext
|
||||
let c_i = match tag.ciphertexts.get(i) {
|
||||
|
@ -87,11 +87,11 @@ impl FuzzyMetaDetectionKey {
|
|||
}
|
||||
|
||||
/// A public identity that others can create tags for.
|
||||
pub struct FuzzyMetaPublicKey(Vec<RistrettoPoint>);
|
||||
pub struct FuzzyPublicKey(Vec<RistrettoPoint>);
|
||||
|
||||
impl FuzzyMetaPublicKey {
|
||||
impl FuzzyPublicKey {
|
||||
/// generate a new tag for this public key
|
||||
pub fn generate_tag(&self) -> FuzzyMetaTag {
|
||||
pub fn generate_tag(&self) -> FuzzyTag {
|
||||
let mut rng = OsRng::default();
|
||||
let g = RISTRETTO_BASEPOINT_POINT;
|
||||
|
||||
|
@ -104,7 +104,7 @@ impl FuzzyMetaPublicKey {
|
|||
// construct the ciphertext portion of the tag
|
||||
let mut ciphertexts = BitVec::new();
|
||||
for (_i, h_i) in self.0.iter().enumerate() {
|
||||
let k_i = FuzzyMetaTagKeyPair::h(u, h_i.mul(r), w);
|
||||
let k_i = FuzzyTagKeyPair::h(u, h_i.mul(r), w);
|
||||
// encrypt a plaintext of all 1's
|
||||
let c_i = k_i ^ 0x01;
|
||||
ciphertexts.push(c_i == 0x01);
|
||||
|
@ -125,14 +125,14 @@ impl FuzzyMetaPublicKey {
|
|||
// used to derive the key.
|
||||
|
||||
// finally calculate a `y` = 1/r * (z-m) which will be used to re-derive `w`
|
||||
let m = FuzzyMetaTagKeyPair::g(u, &ciphertexts);
|
||||
let m = FuzzyTagKeyPair::g(u, &ciphertexts);
|
||||
let y = r.invert().mul(z.sub(m));
|
||||
|
||||
return FuzzyMetaTag { u, y, ciphertexts };
|
||||
return FuzzyTag { u, y, ciphertexts };
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for FuzzyMetaTag {
|
||||
impl Display for FuzzyTag {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
|
@ -145,19 +145,19 @@ impl Display for FuzzyMetaTag {
|
|||
}
|
||||
|
||||
/// An identity keypair for generating and validating fuzzy meta tags.
|
||||
pub struct FuzzyMetaTagKeyPair {
|
||||
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)
|
||||
pub secret_key: FuzzyMetaSecretKey,
|
||||
pub secret_key: FuzzySecretKey,
|
||||
/// the public key - this can be given to people who you want to contact you
|
||||
pub public_key: FuzzyMetaPublicKey,
|
||||
pub public_key: FuzzyPublicKey,
|
||||
}
|
||||
|
||||
impl FuzzyMetaTagKeyPair {
|
||||
impl FuzzyTagKeyPair {
|
||||
/// Generate a new Key Pair given a security parameter `gamma`. Tags generated for a given
|
||||
/// `FuzzyMetaPublicKey::flag` will pass the `FuzzyMetaDetectionKey::test` for other public
|
||||
/// `FuzzyPublicKey::flag` will pass the `FuzzyDetectionKey::test` for other public
|
||||
/// keys with probability $ 2 ^ -8 $
|
||||
pub fn generate(gamma: usize) -> FuzzyMetaTagKeyPair {
|
||||
pub fn generate(gamma: usize) -> FuzzyTagKeyPair {
|
||||
let mut rng = OsRng::default();
|
||||
let g = RISTRETTO_BASEPOINT_POINT;
|
||||
let mut s_keys = vec![];
|
||||
|
@ -168,15 +168,15 @@ impl FuzzyMetaTagKeyPair {
|
|||
s_keys.push(sk_i);
|
||||
p_keys.push(pk_i);
|
||||
}
|
||||
FuzzyMetaTagKeyPair {
|
||||
secret_key: FuzzyMetaSecretKey { 0: s_keys },
|
||||
public_key: FuzzyMetaPublicKey { 0: p_keys },
|
||||
FuzzyTagKeyPair {
|
||||
secret_key: FuzzySecretKey { 0: s_keys },
|
||||
public_key: FuzzyPublicKey { 0: p_keys },
|
||||
}
|
||||
}
|
||||
|
||||
/// extract a detection key for a given false positive (p = 2^-n)
|
||||
/// a facade for an extraction of the encapsulated secret key
|
||||
pub fn extract(&self, n: usize) -> FuzzyMetaDetectionKey {
|
||||
pub fn extract(&self, n: usize) -> FuzzyDetectionKey {
|
||||
self.secret_key.extract(n)
|
||||
}
|
||||
|
||||
|
@ -203,11 +203,11 @@ impl FuzzyMetaTagKeyPair {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::FuzzyMetaTagKeyPair;
|
||||
use crate::FuzzyTagKeyPair;
|
||||
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
let key = FuzzyMetaTagKeyPair::generate(24);
|
||||
let key = FuzzyTagKeyPair::generate(24);
|
||||
let tag = key.public_key.generate_tag();
|
||||
let detection_key = key.extract(10);
|
||||
println!("{}", serde_json::to_string(&tag).unwrap());
|
||||
|
@ -217,7 +217,7 @@ mod tests {
|
|||
#[test]
|
||||
fn correctness() {
|
||||
let number_of_messages = 100;
|
||||
let key = FuzzyMetaTagKeyPair::generate(16);
|
||||
let key = FuzzyTagKeyPair::generate(16);
|
||||
for i in 0..number_of_messages {
|
||||
let tag = key.public_key.generate_tag();
|
||||
println!("{}: {}", i, tag);
|
||||
|
@ -229,10 +229,10 @@ mod tests {
|
|||
fn false_postives() {
|
||||
let gamma = 8;
|
||||
let number_of_messages = 1000;
|
||||
let key = FuzzyMetaTagKeyPair::generate(gamma);
|
||||
let key = FuzzyTagKeyPair::generate(gamma);
|
||||
let mut false_positives = 0;
|
||||
for _i in 0..number_of_messages {
|
||||
let key2 = FuzzyMetaTagKeyPair::generate(gamma);
|
||||
let key2 = FuzzyTagKeyPair::generate(gamma);
|
||||
let tag = key2.public_key.generate_tag();
|
||||
assert!(key2.extract(3).test_tag(&tag));
|
||||
if key.secret_key.extract(3).test_tag(&tag) == true {
|
||||
|
|
Loading…
Reference in New Issue