Clean up benchmarks, move RNG to function parameters + optimize generation
This commit is contained in:
parent
1124ffc1a6
commit
2d73a43d7f
16
README.md
16
README.md
|
@ -104,12 +104,14 @@ validate against a random public key with a maximum probability of _2^-gamma_.
|
|||
Once in possession of a tagging key, a party in a metadata resistant app can use it to generate tags:
|
||||
|
||||
use fuzzytags::RootSecret;
|
||||
use rand::rngs::OsRng;
|
||||
let secret = RootSecret::<24>::generate();
|
||||
let tagging_key = secret.tagging_key();
|
||||
|
||||
// Give public key to a another party...
|
||||
// and then they can do...
|
||||
let tag = tagging_key.generate_tag();
|
||||
let mut rng = OsRng::default();
|
||||
let tag = tagging_key.generate_tag(&mut rng);
|
||||
|
||||
These tags can then be attached to a message in a metadata resistant system.
|
||||
|
||||
|
@ -120,6 +122,7 @@ First it is necessary to extract a detection key for a given false positive prob
|
|||
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.:
|
||||
|
||||
use fuzzytags::RootSecret;
|
||||
use rand::rngs::OsRng;
|
||||
let secret = RootSecret::<24>::generate();
|
||||
let tagging_key = secret.tagging_key();
|
||||
// extract a detection key
|
||||
|
@ -127,7 +130,8 @@ This extracted key can then be given to an adversarial server. The server can th
|
|||
|
||||
// Give the tagging key to a another party...
|
||||
// and then they can do...
|
||||
let tag = tagging_key.generate_tag();
|
||||
let mut rng = OsRng::default();
|
||||
let tag = tagging_key.generate_tag(&mut rng);
|
||||
|
||||
// The server can now do this:
|
||||
if detection_key.test_tag(&tag) {
|
||||
|
@ -144,6 +148,8 @@ opens up applications like **multiple broadcast** and **deniable sending**.
|
|||
|
||||
|
||||
use fuzzytags::{RootSecret, TaggingKey};
|
||||
use rand::rngs::OsRng;
|
||||
let mut rng = OsRng::default();
|
||||
let secret_1 = RootSecret::<24>::generate();
|
||||
let secret_2 = RootSecret::<24>::generate();
|
||||
let tagging_key_1 = secret_1.tagging_key(); // give this to a sender
|
||||
|
@ -151,7 +157,7 @@ opens up applications like **multiple broadcast** and **deniable sending**.
|
|||
// Will validate for detection keys derived from both secret_1 and secret_2 up
|
||||
// to n=8
|
||||
#[cfg(feature = "entangled")]
|
||||
let tag = TaggingKey::generate_entangled_tag(vec![tagging_key_1,tagging_key_2], 8);
|
||||
let tag = TaggingKey::generate_entangled_tag(vec![tagging_key_1,tagging_key_2], &mut rng, 8);
|
||||
|
||||
## Serialization
|
||||
|
||||
|
@ -161,13 +167,15 @@ of different approaches e.g.:
|
|||
|
||||
use fuzzytags::RootSecret;
|
||||
use fuzzytags::Tag;
|
||||
use rand::rngs::OsRng;
|
||||
|
||||
let mut rng = OsRng::default();
|
||||
let secret = RootSecret::<24>::generate();
|
||||
let tagging_key = secret.tagging_key();
|
||||
|
||||
// Give public key to a another party...
|
||||
// and then they can do...
|
||||
let tag = tagging_key.generate_tag();
|
||||
let tag = tagging_key.generate_tag(&mut rng);
|
||||
|
||||
// An example using JSON serialization...see serde doc for other formats:
|
||||
let serialized_tag = serde_json::to_string(&tag).unwrap();
|
||||
|
|
|
@ -4,8 +4,8 @@ use std::time::Duration;
|
|||
|
||||
fn benchmark_entangled(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("entangling");
|
||||
group.measurement_time(Duration::new(10, 0));
|
||||
group.sample_size(10);
|
||||
group.measurement_time(Duration::new(5000, 0));
|
||||
group.sample_size(50);
|
||||
let secret_key_1 = RootSecret::<24>::generate();
|
||||
let secret_key_2 = RootSecret::<24>::generate();
|
||||
let public_key_1 = secret_key_1.tagging_key();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
use fuzzytags::{RootSecret, TaggingKey};
|
||||
use rand::rngs::OsRng;
|
||||
use std::time::Duration;
|
||||
|
||||
fn benchmark_generate_tag(c: &mut Criterion) {
|
||||
|
@ -7,10 +8,11 @@ fn benchmark_generate_tag(c: &mut Criterion) {
|
|||
group.measurement_time(Duration::new(10, 0));
|
||||
group.sample_size(1000);
|
||||
let secret_key = RootSecret::<24>::generate();
|
||||
let mut rng = OsRng::default();
|
||||
let public_key = secret_key.tagging_key();
|
||||
for p in [5, 10, 15].iter() {
|
||||
let public_key = secret_key.tagging_key();
|
||||
group.bench_with_input(BenchmarkId::from_parameter(p), p, |b, _gamma| {
|
||||
b.iter(|| public_key.generate_tag())
|
||||
b.iter(|| public_key.generate_tag(&mut rng))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -20,11 +22,12 @@ fn benchmark_test_tag(c: &mut Criterion) {
|
|||
group.measurement_time(Duration::new(10, 0));
|
||||
group.sample_size(1000);
|
||||
let secret_key = RootSecret::<24>::generate();
|
||||
let mut rng = OsRng::default();
|
||||
|
||||
for p in [5, 10, 15].iter() {
|
||||
let tag = secret_key.tagging_key().generate_tag();
|
||||
for p in [5, 10, 15, 24].iter() {
|
||||
let detection_key = secret_key.extract_detection_key(*p);
|
||||
group.bench_with_input(BenchmarkId::from_parameter(p), p, |b, _gamma| {
|
||||
let tag = secret_key.tagging_key().generate_tag(&mut rng);
|
||||
b.iter(|| detection_key.test_tag(&tag))
|
||||
});
|
||||
}
|
||||
|
|
73
src/lib.rs
73
src/lib.rs
|
@ -11,6 +11,7 @@ use curve25519_dalek::ristretto::{CompressedRistretto, RistrettoPoint};
|
|||
use curve25519_dalek::scalar::Scalar;
|
||||
use curve25519_dalek::traits::MultiscalarMul;
|
||||
use rand::rngs::OsRng;
|
||||
use rand::{CryptoRng, RngCore};
|
||||
use serde::{de::Visitor, Deserialize, Deserializer, Serialize, Serializer};
|
||||
use sha3::{Sha3_256, Sha3_512};
|
||||
use std::convert::TryFrom;
|
||||
|
@ -107,6 +108,7 @@ impl<const GAMMA: u8> Tag<{ GAMMA }> {
|
|||
/// Ciphertext is right-padded with zeros to the nearest byte
|
||||
/// You probably want to use one of the many serde `serialize` apis instead (see README)
|
||||
/// ```
|
||||
/// use rand::rngs::OsRng;
|
||||
/// use fuzzytags::RootSecret;
|
||||
/// let secret = RootSecret::<24>::generate();
|
||||
/// let tagging_key = secret.tagging_key();
|
||||
|
@ -115,7 +117,8 @@ impl<const GAMMA: u8> Tag<{ GAMMA }> {
|
|||
///
|
||||
/// // Give tagging key to a another party...
|
||||
/// // and then they can do...
|
||||
/// let tag = tagging_key.generate_tag();
|
||||
/// let mut rng = OsRng::default();
|
||||
/// let tag = tagging_key.generate_tag(&mut rng);
|
||||
/// let compressed_tag = tag.compress();
|
||||
/// ```
|
||||
pub fn compress(&self) -> Vec<u8> {
|
||||
|
@ -137,7 +140,9 @@ impl<const GAMMA: u8> Tag<{ GAMMA }> {
|
|||
///
|
||||
/// // Give tagging key to a another party...
|
||||
/// // and then they can do...
|
||||
/// let tag = tagging_key.generate_tag();
|
||||
/// use rand::rngs::OsRng;
|
||||
/// let mut rng = OsRng::default();
|
||||
/// let tag = tagging_key.generate_tag(&mut rng);
|
||||
/// let compressed_tag = tag.compress();
|
||||
/// let decompressed_tag = Tag::decompress(&compressed_tag).unwrap();
|
||||
/// assert_eq!(tag, decompressed_tag);
|
||||
|
@ -334,7 +339,9 @@ impl<const GAMMA: u8> DetectionKey<{ GAMMA }> {
|
|||
///
|
||||
/// // Give tagging key to a another party...
|
||||
/// // and then they can do...
|
||||
/// let tag = tagging_key.generate_tag();
|
||||
/// use rand::rngs::OsRng;
|
||||
/// let mut rng = OsRng::default();
|
||||
/// let tag = tagging_key.generate_tag(&mut rng);
|
||||
///
|
||||
/// // The server can now do this:
|
||||
/// if detection_key.test_tag(&tag) {
|
||||
|
@ -399,7 +406,9 @@ impl<const GAMMA: u8> DetectionKey<{ GAMMA }> {
|
|||
/// let secrets: Vec<RootSecret<24>> = (0..2).map(|_x| RootSecret::<24>::generate()).collect();
|
||||
/// let tagging_keys: Vec<TaggingKey<24>> = secrets.iter().map(|x| x.tagging_key()).collect();
|
||||
/// // it takes ~15 minutes on a standard desktop to find a length=24 match for 2 parties, so for testing let's keep things light
|
||||
/// let entangled_tag = TaggingKey::generate_entangled_tag(tagging_keys, 16);
|
||||
/// use rand::rngs::OsRng;
|
||||
/// let mut rng = OsRng::default();
|
||||
/// let entangled_tag = TaggingKey::generate_entangled_tag(tagging_keys, &mut rng, 16);
|
||||
/// let detection_keys = secrets.iter().map(|x| x.extract_detection_key(16)).collect();
|
||||
///
|
||||
/// let results = DetectionKey::test_tag_bulk(&detection_keys, &entangled_tag);
|
||||
|
@ -495,21 +504,25 @@ impl<const GAMMA: u8> TaggingKey<{ GAMMA }> {
|
|||
/// use fuzzytags::{RootSecret};
|
||||
/// let secret = RootSecret::<24>::generate();
|
||||
/// let tagging_key = secret.tagging_key(); // give this to a sender
|
||||
/// let tag = tagging_key.generate_tag();
|
||||
/// use rand::rngs::OsRng;
|
||||
/// let mut rng = OsRng::default();
|
||||
/// let tag = tagging_key.generate_tag(&mut rng);
|
||||
/// ```
|
||||
pub fn generate_tag(&self) -> Tag<{ GAMMA }> {
|
||||
let mut rng = OsRng::default();
|
||||
let g = RISTRETTO_BASEPOINT_POINT;
|
||||
|
||||
pub fn generate_tag<R: RngCore + CryptoRng>(&self, rng: &mut R) -> Tag<{ GAMMA }> {
|
||||
// generate some random points...
|
||||
let r = Scalar::random(&mut rng);
|
||||
let u = g.mul(r);
|
||||
let z = Scalar::random(&mut rng);
|
||||
let w = g.mul(z);
|
||||
let r = Scalar::random(rng);
|
||||
let u = RISTRETTO_BASEPOINT_POINT.mul(r);
|
||||
|
||||
let z = Scalar::random(rng);
|
||||
let w = RISTRETTO_BASEPOINT_POINT.mul(z);
|
||||
|
||||
// precompute the first part of the `H` hash function
|
||||
let pre_h = RootSecret::<GAMMA>::pre_h(u, w);
|
||||
|
||||
// construct the ciphertext portion of the tag
|
||||
let mut ciphertexts = BitVec::new();
|
||||
for (_i, h_i) in self.0.iter().enumerate() {
|
||||
let mut ciphertexts = BitVec::with_capacity(GAMMA.into());
|
||||
|
||||
for h_i in self.0.iter() {
|
||||
let k_i = RootSecret::<GAMMA>::post_h(pre_h.clone(), h_i.mul(r));
|
||||
// encrypt a plaintext of all 1's
|
||||
let c_i = k_i ^ 0x01;
|
||||
|
@ -551,13 +564,14 @@ impl<const GAMMA: u8> TaggingKey<{ GAMMA }> {
|
|||
/// // Will validate for detection keys derived from both secret_1 and secret_2 up
|
||||
/// // to n=8
|
||||
/// // Sender can now do...tag will validate on detection keys of length 8 or lower.
|
||||
/// let tag = TaggingKey::generate_entangled_tag(vec![tagging_key_1,tagging_key_2], 8);
|
||||
/// use rand::rngs::OsRng;
|
||||
/// let mut rng = OsRng::default();
|
||||
/// let tag = TaggingKey::generate_entangled_tag(vec![tagging_key_1,tagging_key_2], &mut rng, 8);
|
||||
/// ```
|
||||
pub fn generate_entangled_tag(tagging_keys: Vec<TaggingKey<{ GAMMA }>>, length: usize) -> Tag<{ GAMMA }> {
|
||||
let mut rng = OsRng::default();
|
||||
pub fn generate_entangled_tag<R: RngCore + CryptoRng>(tagging_keys: Vec<TaggingKey<{ GAMMA }>>, rng: &mut R, length: usize) -> Tag<{ GAMMA }> {
|
||||
let g = RISTRETTO_BASEPOINT_POINT;
|
||||
// generate some random points...
|
||||
let r = Scalar::random(&mut rng);
|
||||
let r = Scalar::random(rng);
|
||||
let u = g.mul(r);
|
||||
|
||||
// Compute and cache some public points that we will be using over and over again
|
||||
|
@ -621,7 +635,8 @@ mod tests {
|
|||
|
||||
// Give tagging key to a another party...
|
||||
// and then they can do...
|
||||
let tag = tagging_key.generate_tag();
|
||||
let mut rng = OsRng::default();
|
||||
let tag = tagging_key.generate_tag(&mut rng);
|
||||
let compressed_tag = tag.compress();
|
||||
let decompressed_tag = Tag::<24>::decompress(&compressed_tag).unwrap();
|
||||
assert_eq!(tag, decompressed_tag);
|
||||
|
@ -630,8 +645,10 @@ mod tests {
|
|||
#[test]
|
||||
fn test_serialization() {
|
||||
// generate some new keys...
|
||||
|
||||
let secret = RootSecret::<15>::generate();
|
||||
let tag = secret.tagging_key().generate_tag();
|
||||
let mut rng = OsRng::default();
|
||||
let tag = secret.tagging_key().generate_tag(&mut rng);
|
||||
let detection_key = secret.extract_detection_key(10);
|
||||
let serialized_tag = serde_json::to_string(&tag).unwrap();
|
||||
println!("{}", serialized_tag);
|
||||
|
@ -641,7 +658,7 @@ mod tests {
|
|||
|
||||
// generate some new keys...
|
||||
let secret = RootSecret::<24>::generate();
|
||||
let tag = secret.tagging_key().generate_tag();
|
||||
let tag = secret.tagging_key().generate_tag(&mut rng);
|
||||
let detection_key = secret.extract_detection_key(10);
|
||||
let serialized_tag = serde_json::to_string(&tag).unwrap();
|
||||
let deserialized_tag: Tag<24> = serde_json::from_str(&serialized_tag).unwrap();
|
||||
|
@ -680,7 +697,8 @@ mod tests {
|
|||
let secrets: Vec<RootSecret<24>> = (0..2).map(|_x| RootSecret::<24>::generate()).collect();
|
||||
let tagging_keys: Vec<TaggingKey<24>> = secrets.iter().map(|x| x.tagging_key()).collect();
|
||||
// it takes ~15 minutes on a standard desktop to find a length=24 match for 2 parties, so for testing let's keep things light
|
||||
let entangled_tag = TaggingKey::generate_entangled_tag(tagging_keys, 16);
|
||||
let mut rng = OsRng::default();
|
||||
let entangled_tag = TaggingKey::generate_entangled_tag(tagging_keys, &mut rng, 16);
|
||||
println!("{}", entangled_tag);
|
||||
for secret in secrets.iter() {
|
||||
let detection_key = secret.extract_detection_key(16);
|
||||
|
@ -696,7 +714,8 @@ mod tests {
|
|||
let secrets: Vec<RootSecret<24>> = (0..2).map(|_x| RootSecret::<24>::generate()).collect();
|
||||
let tagging_keys: Vec<TaggingKey<24>> = secrets.iter().map(|x| x.tagging_key()).collect();
|
||||
// it takes ~15 minutes on a standard desktop to find a length=24 match for 2 parties, so for testing let's keep things light
|
||||
let entangled_tag = TaggingKey::generate_entangled_tag(tagging_keys, 16);
|
||||
let mut rng = OsRng::default();
|
||||
let entangled_tag = TaggingKey::generate_entangled_tag(tagging_keys, &mut rng, 16);
|
||||
let detection_keys = secrets
|
||||
.iter()
|
||||
.map(|x| x.extract_detection_key(16))
|
||||
|
@ -710,8 +729,9 @@ mod tests {
|
|||
fn correctness() {
|
||||
let number_of_messages = 100;
|
||||
let secret = RootSecret::<16>::generate();
|
||||
let mut rng = OsRng::default();
|
||||
for i in 0..number_of_messages {
|
||||
let tag = secret.tagging_key().generate_tag();
|
||||
let tag = secret.tagging_key().generate_tag(&mut rng);
|
||||
println!("{}: {}", i, tag);
|
||||
assert!(secret.extract_detection_key(5).test_tag(&tag));
|
||||
}
|
||||
|
@ -769,9 +789,10 @@ mod tests {
|
|||
let number_of_messages = 1000;
|
||||
let secret = RootSecret::<24>::generate();
|
||||
let mut false_positives = 0;
|
||||
let mut rng = OsRng::default();
|
||||
for _i in 0..number_of_messages {
|
||||
let secret2 = RootSecret::<24>::generate();
|
||||
let tag = secret2.tagging_key().generate_tag();
|
||||
let tag = secret2.tagging_key().generate_tag(&mut rng);
|
||||
assert!(secret2.extract_detection_key(3).test_tag(&tag));
|
||||
if secret.extract_detection_key(3).test_tag(&tag) == true {
|
||||
false_positives += 1;
|
||||
|
|
Loading…
Reference in New Issue