Browse Source

Settle on a name

trunk
Sarah Jamie Lewis 2 years ago
parent
commit
0040e0c905
  1. 2
      Cargo.toml
  2. 6
      README.md
  3. 6
      benches/fuzzy_tags_benches.rs
  4. 72
      src/lib.rs

2
Cargo.toml

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

6
README.md

@ -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.

6
benches/fuzzy_tags_benches.rs

@ -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

@ -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…
Cancel
Save