Settle on a name

This commit is contained in:
Sarah Jamie Lewis 2021-01-30 11:33:30 -08:00
parent 0f9720a215
commit 0040e0c905
4 changed files with 43 additions and 43 deletions

View File

@ -1,5 +1,5 @@
[package] [package]
name = "fuzzymetatag" name = "fuzzytags"
version = "0.1.0" version = "0.1.0"
authors = ["Sarah Jamie Lewis <sarah@openprivacy.ca>"] authors = ["Sarah Jamie Lewis <sarah@openprivacy.ca>"]
edition = "2018" edition = "2018"

View File

@ -1,4 +1,4 @@
# fuzzymetatag # FuzzyTags
Anonymous messaging systems (and other privacy-preserving applications) often require a mechanism for one party Anonymous messaging systems (and other privacy-preserving applications) often require a mechanism for one party
to learn that another party has messaged them. 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! 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: properties:
* Correctness: Valid tags constructed for a specific public key will always validate when tested using the detection key * 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: Generate a key pair:
let gamma = 3; 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 `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. messaging service / privacy-preserving application.

View File

@ -1,11 +1,11 @@
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion}; use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
use fuzzymetatag::FuzzyMetaTagKeyPair; use fuzzytags::FuzzyTagKeyPair;
use std::time::Duration; use std::time::Duration;
fn benchmark_generate_tag(c: &mut Criterion) { fn benchmark_generate_tag(c: &mut Criterion) {
let mut group = c.benchmark_group("generate_tags"); let mut group = c.benchmark_group("generate_tags");
group.measurement_time(Duration::new(10, 0)); group.measurement_time(Duration::new(10, 0));
let key = FuzzyMetaTagKeyPair::generate(24); let key = FuzzyTagKeyPair::generate(24);
for p in [5, 10, 15].iter() { 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())); 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) { fn benchmark_test_tag(c: &mut Criterion) {
let mut group = c.benchmark_group("test_tags"); let mut group = c.benchmark_group("test_tags");
group.measurement_time(Duration::new(10, 0)); group.measurement_time(Duration::new(10, 0));
let key = FuzzyMetaTagKeyPair::generate(24); let key = FuzzyTagKeyPair::generate(24);
for p in [5, 10, 15].iter() { for p in [5, 10, 15].iter() {
let tag = key.public_key.generate_tag(); let tag = key.public_key.generate_tag();
let detection_key = key.extract(*p); let detection_key = key.extract(*p);

View File

@ -14,41 +14,41 @@ use std::fmt;
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use std::ops::{Add, Mul, Sub}; use std::ops::{Add, Mul, Sub};
/// A tag is a probabilistic cryptographic structure. When constructed for a given `FuzzyMetaPublicKey` /// A tag is a probabilistic cryptographic structure. When constructed for a given `FuzzyPublicKey`
/// it will pass the `FuzzyMetaDetectionKey::test` 100% of the time. For other public keys /// 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. /// it will pass the test with probability `gamma` related to the security parameter of the system.
/// This system provides the following security properties: /// 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 /// * 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 (_γ_) /// * 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) /// * 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)] #[derive(Debug, Serialize, Deserialize)]
pub struct FuzzyMetaTag { pub struct FuzzyTag {
u: RistrettoPoint, u: RistrettoPoint,
y: Scalar, y: Scalar,
ciphertexts: BitVec, ciphertexts: BitVec,
} }
/// The complete secret key. Can't directly be used for testing. Instead you will need to generate /// The complete secret key. Can't directly be used for testing. Instead you will need to generate
/// a FuzzyMetaDetectionKey using extract /// a FuzzyDetectionKey using extract
pub struct FuzzyMetaSecretKey(Vec<Scalar>); pub struct FuzzySecretKey(Vec<Scalar>);
impl FuzzyMetaSecretKey { impl FuzzySecretKey {
/// extract a detection key for a given false positive (p = 2^-n) /// 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(); 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 /// the derived public key with probability p
#[derive(Debug, Serialize, Deserialize)] #[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 /// returns true if the tag was intended for this key
pub fn test_tag(&self, tag: &FuzzyMetaTag) -> bool { pub fn test_tag(&self, tag: &FuzzyTag) -> bool {
let m = FuzzyMetaTagKeyPair::g(tag.u, &tag.ciphertexts); let m = FuzzyTagKeyPair::g(tag.u, &tag.ciphertexts);
let g = RISTRETTO_BASEPOINT_POINT; let g = RISTRETTO_BASEPOINT_POINT;
@ -66,7 +66,7 @@ impl FuzzyMetaDetectionKey {
let mut result = true; let mut result = true;
for (i, x_i) in self.0.iter().enumerate() { for (i, x_i) in self.0.iter().enumerate() {
// re-derive the key from the tag // 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 // calculate the "original" plaintext
let c_i = match tag.ciphertexts.get(i) { let c_i = match tag.ciphertexts.get(i) {
@ -87,11 +87,11 @@ impl FuzzyMetaDetectionKey {
} }
/// A public identity that others can create tags for. /// 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 /// 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 mut rng = OsRng::default();
let g = RISTRETTO_BASEPOINT_POINT; let g = RISTRETTO_BASEPOINT_POINT;
@ -104,7 +104,7 @@ impl FuzzyMetaPublicKey {
// construct the ciphertext portion of the tag // construct the ciphertext portion of the tag
let mut ciphertexts = BitVec::new(); let mut ciphertexts = BitVec::new();
for (_i, h_i) in self.0.iter().enumerate() { 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 // 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);
@ -125,14 +125,14 @@ impl FuzzyMetaPublicKey {
// used to derive the key. // used to derive the key.
// finally calculate a `y` = 1/r * (z-m) which will be used to re-derive `w` // 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)); 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 { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!( write!(
f, f,
@ -145,19 +145,19 @@ impl Display for FuzzyMetaTag {
} }
/// An identity keypair for generating and validating fuzzy meta tags. /// 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 /// 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) /// 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 /// 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 /// 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 $ /// keys with probability $ 2 ^ -8 $
pub fn generate(gamma: usize) -> FuzzyMetaTagKeyPair { pub fn generate(gamma: usize) -> FuzzyTagKeyPair {
let mut rng = OsRng::default(); let mut rng = OsRng::default();
let g = RISTRETTO_BASEPOINT_POINT; let g = RISTRETTO_BASEPOINT_POINT;
let mut s_keys = vec![]; let mut s_keys = vec![];
@ -168,15 +168,15 @@ impl FuzzyMetaTagKeyPair {
s_keys.push(sk_i); s_keys.push(sk_i);
p_keys.push(pk_i); p_keys.push(pk_i);
} }
FuzzyMetaTagKeyPair { FuzzyTagKeyPair {
secret_key: FuzzyMetaSecretKey { 0: s_keys }, secret_key: FuzzySecretKey { 0: s_keys },
public_key: FuzzyMetaPublicKey { 0: p_keys }, public_key: FuzzyPublicKey { 0: p_keys },
} }
} }
/// extract a detection key for a given false positive (p = 2^-n) /// extract a detection key for a given false positive (p = 2^-n)
/// a facade for an extraction of the encapsulated secret key /// 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) self.secret_key.extract(n)
} }
@ -203,11 +203,11 @@ impl FuzzyMetaTagKeyPair {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::FuzzyMetaTagKeyPair; use crate::FuzzyTagKeyPair;
#[test] #[test]
fn test_serialization() { fn test_serialization() {
let key = FuzzyMetaTagKeyPair::generate(24); let key = FuzzyTagKeyPair::generate(24);
let tag = key.public_key.generate_tag(); let tag = key.public_key.generate_tag();
let detection_key = key.extract(10); let detection_key = key.extract(10);
println!("{}", serde_json::to_string(&tag).unwrap()); println!("{}", serde_json::to_string(&tag).unwrap());
@ -217,7 +217,7 @@ mod tests {
#[test] #[test]
fn correctness() { fn correctness() {
let number_of_messages = 100; let number_of_messages = 100;
let key = FuzzyMetaTagKeyPair::generate(16); let key = FuzzyTagKeyPair::generate(16);
for i in 0..number_of_messages { for i in 0..number_of_messages {
let tag = key.public_key.generate_tag(); let tag = key.public_key.generate_tag();
println!("{}: {}", i, tag); println!("{}: {}", i, tag);
@ -229,10 +229,10 @@ mod tests {
fn false_postives() { fn false_postives() {
let gamma = 8; let gamma = 8;
let number_of_messages = 1000; let number_of_messages = 1000;
let key = FuzzyMetaTagKeyPair::generate(gamma); let key = FuzzyTagKeyPair::generate(gamma);
let mut false_positives = 0; let mut false_positives = 0;
for _i in 0..number_of_messages { for _i in 0..number_of_messages {
let key2 = FuzzyMetaTagKeyPair::generate(gamma); let key2 = FuzzyTagKeyPair::generate(gamma);
let tag = key2.public_key.generate_tag(); let tag = key2.public_key.generate_tag();
assert!(key2.extract(3).test_tag(&tag)); assert!(key2.extract(3).test_tag(&tag));
if key.secret_key.extract(3).test_tag(&tag) == true { if key.secret_key.extract(3).test_tag(&tag) == true {