Convert API to const_generics

This commit is contained in:
Sarah Jamie Lewis 2021-02-04 12:54:09 -08:00
parent a0d2cb7d12
commit e26981e6af
3 changed files with 122 additions and 119 deletions

View File

@ -69,8 +69,7 @@ provided them (depending on the efficiency of the decryption method).
Generate a key pair:
use fuzzytags::FuzzySecretKey;
let gamma = 24;
let secret_key = FuzzySecretKey::generate(gamma);
let secret_key = FuzzySecretKey::<24>::generate();
`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.
@ -85,8 +84,7 @@ validate against a random public key with a maximum probability of _2^-gamma_.
Once in possession of a public key, a party in a metadata resistant app can use it to generate tags:
use fuzzytags::FuzzySecretKey;
let gamma = 24;
let secret_key = FuzzySecretKey::generate(gamma);
let secret_key = FuzzySecretKey::<24>::generate();
let public_key = secret_key.public_key();
// Give public key to a another party...
@ -102,8 +100,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::FuzzySecretKey;
let gamma = 24;
let secret_key = FuzzySecretKey::generate(gamma);
let secret_key = FuzzySecretKey::<24>::generate();
let public_key = secret_key.public_key();
// extract a detection key
let detection_key = secret_key.extract(5);
@ -127,8 +124,8 @@ opens up applications like **multiple broadcast** and **deniable sending**.
use fuzzytags::{FuzzySecretKey, FuzzyPublicKey};
let secret_key_1 = FuzzySecretKey::generate(24);
let secret_key_2 = FuzzySecretKey::generate(24);
let secret_key_1 = FuzzySecretKey::<24>::generate();
let secret_key_2 = FuzzySecretKey::<24>::generate();
let public_key_1 = secret_key_1.public_key(); // give this to a sender
let public_key_2 = secret_key_2.public_key(); // give this to a sender
// Will validate for detection keys derived from both secret_key_1 and secret_key_2 up
@ -145,8 +142,7 @@ of different approaches e.g.:
use fuzzytags::FuzzySecretKey;
use fuzzytags::FuzzyTag;
let gamma = 24;
let secret_key = FuzzySecretKey::generate(gamma);
let secret_key = FuzzySecretKey::<24>::generate();
let public_key = secret_key.public_key();
// Give public key to a another party...
@ -158,7 +154,7 @@ of different approaches e.g.:
println!("Serialized: {}", serialized_tag);
// We can then deserialize with:
let deserialized_tag: Result<FuzzyTag, serde_json::Error> = serde_json::from_str(&serialized_tag);
let deserialized_tag: Result<FuzzyTag<24>, serde_json::Error> = serde_json::from_str(&serialized_tag);
println!("Deserialized: {}", deserialized_tag.unwrap());
## Benchmarks

View File

@ -19,7 +19,8 @@ fn_single_line = false
where_single_line = false
imports_indent = "Block"
imports_layout = "Mixed"
merge_imports = false
imports_granularity = "Preserve"
group_imports = "Preserve"
reorder_imports = true
reorder_modules = true
reorder_impl_items = false
@ -34,6 +35,7 @@ overflow_delimited_expr = false
struct_field_align_threshold = 0
enum_discrim_align_threshold = 0
match_arm_blocks = true
match_arm_leading_pipes = "Never"
force_multiline_blocks = false
fn_args_layout = "Tall"
brace_style = "SameLineWhere"
@ -52,7 +54,7 @@ use_field_init_shorthand = false
force_explicit_abi = true
condense_wildcard_suffixes = false
color = "Auto"
required_version = "1.4.21"
required_version = "1.4.34"
unstable_features = false
disable_all_formatting = false
skip_children = false

View File

@ -1,7 +1,6 @@
#![deny(missing_docs)]
#![feature(array_methods)]
#![feature(external_doc)]
#![feature(in_band_lifetimes)]
#![feature(const_generics)]
#![doc(include = "../README.md")]
#![doc(include = "../ANONYMITY.md")]
use bit_vec::BitVec;
@ -25,19 +24,19 @@ use brute_force::brute_force;
/// 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.
/// 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(Clone, Debug, Eq, PartialEq)]
pub struct FuzzyTag {
pub struct FuzzyTag<const GAMMA: u8> {
u: RistrettoPoint,
y: Scalar,
ciphertexts: BitVec,
}
impl Serialize for FuzzyTag {
impl<const GAMMA: u8> Serialize for FuzzyTag<{ GAMMA }> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
@ -52,21 +51,21 @@ impl Serialize for FuzzyTag {
}
}
impl<'de> Deserialize<'de> for FuzzyTag {
impl<'de, const GAMMA: u8> Deserialize<'de> for FuzzyTag<{ GAMMA }> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct FuzzyTagVisitor;
struct FuzzyTagVisitor<const GAMMA: u8>;
impl<'de> Visitor<'de> for FuzzyTagVisitor {
type Value = FuzzyTag;
impl<'de, const GAMMA: u8> Visitor<'de> for FuzzyTagVisitor<{ GAMMA }> {
type Value = FuzzyTag<{ GAMMA }>;
fn expecting(&self, formatter: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
formatter.write_str("64 bytes + gamma+bits of data")
formatter.write_str("64 bytes + GAMMA+bits of data")
}
fn visit_seq<A>(self, mut seq: A) -> Result<FuzzyTag, A::Error>
fn visit_seq<A>(self, mut seq: A) -> Result<FuzzyTag<{ GAMMA }>, A::Error>
where
A: serde::de::SeqAccess<'de>,
{
@ -80,24 +79,23 @@ impl<'de> Deserialize<'de> for FuzzyTag {
_ => break,
}
}
FuzzyTag::decompress(&bytes).ok_or(serde::de::Error::custom("invalid fuzzytag"))
FuzzyTag::<GAMMA>::decompress(&bytes).ok_or(serde::de::Error::custom("invalid fuzzytag"))
}
}
// support up to gamma = 64
deserializer.deserialize_tuple(72, FuzzyTagVisitor)
// support up to GAMMA = 64
deserializer.deserialize_tuple(72, FuzzyTagVisitor::<GAMMA>)
}
}
impl FuzzyTag {
impl<const GAMMA: u8> FuzzyTag<{ GAMMA }> {
/// An optimal sized copy of the tag
/// Compressed u || y || ciphertext
/// 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 fuzzytags::FuzzySecretKey;
/// let gamma = 24;
/// let secret_key = FuzzySecretKey::generate(gamma);
/// let secret_key = FuzzySecretKey::<24>::generate();
/// let public_key = secret_key.public_key();
/// // extract a detection key
/// let detection_key = secret_key.extract(5);
@ -119,8 +117,7 @@ impl FuzzyTag {
/// You probably want to use one of the many serde `deserialize` apis instead (see README)
/// ```
/// use fuzzytags::{FuzzySecretKey, FuzzyTag};
/// let gamma = 24;
/// let secret_key = FuzzySecretKey::generate(gamma);
/// let secret_key = FuzzySecretKey::<24>::generate();
/// let public_key = secret_key.public_key();
/// // extract a detection key
/// let detection_key = secret_key.extract(5);
@ -132,16 +129,26 @@ impl FuzzyTag {
/// let decompressed_tag = FuzzyTag::decompress(&compressed_tag).unwrap();
/// assert_eq!(tag, decompressed_tag);
/// ```
pub fn decompress(bytes: &[u8]) -> Option<FuzzyTag> {
pub fn decompress(bytes: &[u8]) -> Option<FuzzyTag<{ GAMMA }>> {
if bytes.len() > 64 {
let (u_bytes, rest) = bytes.split_at(32);
let (y_bytes, ciphertext) = rest.split_at(32);
return match CompressedRistretto::from_slice(u_bytes).decompress() {
Some(u) => Some(FuzzyTag {
u,
y: Scalar::from_bits(<[u8; 32]>::try_from(y_bytes).unwrap()),
ciphertexts: BitVec::from_bytes(ciphertext),
}),
// if the ciphertext is too short, then this is an invalid tag
let min_bytes = GAMMA / 8;
if ciphertext.len() < min_bytes as usize {
return None;
}
// This shouldn't actually fail, but for the safety...
let y_bytes_fixed = match <[u8; 32]>::try_from(y_bytes) {
Ok(fixed_size) => fixed_size,
_ => return None,
};
let mut ciphertexts = BitVec::from_bytes(ciphertext);
ciphertexts.truncate(GAMMA as usize);
return match (CompressedRistretto::from_slice(u_bytes).decompress(), Scalar::from_canonical_bytes(y_bytes_fixed)) {
(Some(u), Some(y)) => Some(FuzzyTag { u, y, ciphertexts }),
_ => None,
};
}
@ -149,7 +156,7 @@ impl FuzzyTag {
}
}
impl Display for FuzzyTag {
impl<const GAMMA: u8> Display for FuzzyTag<{ GAMMA }> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
@ -164,35 +171,35 @@ impl Display for 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 {
pub struct FuzzySecretKey<const GAMMA: u8> {
/// 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)
secret_key: Vec<Scalar>,
/// the public key - this can be given to people who you want to contact you
public_key: FuzzyPublicKey,
public_key: FuzzyPublicKey<{ GAMMA }>,
}
impl FuzzySecretKey {
/// Generate a new Key Pair given a security parameter `gamma`. Tags generated for a given
impl<const GAMMA: u8> FuzzySecretKey<{ GAMMA }> {
/// 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::{FuzzySecretKey};
/// let secret_key = FuzzySecretKey::generate(5);
/// let secret_key = FuzzySecretKey::<24>::generate();
/// ```
pub fn generate(gamma: usize) -> FuzzySecretKey {
pub fn generate() -> FuzzySecretKey<{ GAMMA }> {
let mut rng = OsRng::default();
let g = RISTRETTO_BASEPOINT_POINT;
let mut secret_key = vec![];
let mut p_keys = vec![];
for _i in 0..gamma {
for _i in 0..GAMMA {
let sk_i = Scalar::random(&mut rng);
let pk_i = g.mul(sk_i);
secret_key.push(sk_i);
p_keys.push(pk_i);
}
FuzzySecretKey {
FuzzySecretKey::<GAMMA> {
secret_key,
public_key: FuzzyPublicKey { 0: p_keys },
}
@ -202,28 +209,29 @@ impl FuzzySecretKey {
/// Example:
/// ```
/// use fuzzytags::{FuzzySecretKey};
/// let secret_key = FuzzySecretKey::generate(24);
/// let secret_key = FuzzySecretKey::<24>::generate();
/// let detection_key = secret_key.extract(2);
/// ```
pub fn extract(&self, n: usize) -> FuzzyDetectionKey {
pub fn extract(&self, n: usize) -> FuzzyDetectionKey<{ GAMMA }> {
let parts = self.secret_key.iter().take(n).cloned().collect();
FuzzyDetectionKey { 0: parts }
FuzzyDetectionKey::<GAMMA> { 0: parts }
}
/// derive the public key for this key
/// Example:
/// ```
/// use fuzzytags::FuzzySecretKey;
/// let secret_key = FuzzySecretKey::generate(24);
/// let secret_key = FuzzySecretKey::<24>::generate();
/// let public_key = secret_key.public_key();
/// ```
pub fn public_key(&self) -> FuzzyPublicKey {
pub fn public_key(&self) -> FuzzyPublicKey<{ GAMMA }> {
self.public_key.clone()
}
/// a hash function that takes 3 ristretto points as a parameter and outputs 0 or 1.
fn h(u: RistrettoPoint, h: RistrettoPoint, w: RistrettoPoint) -> u8 {
let mut hash = sha3::Sha3_256::new();
hash.update(&[GAMMA]);
hash.update(u.compress().as_bytes());
hash.update(h.compress().as_bytes());
hash.update(w.compress().as_bytes());
@ -233,7 +241,11 @@ impl FuzzySecretKey {
/// a hash function which takes a ristretto point and a vector of ciphertexts and outputs a
/// ristretto scalar.
fn g(u: RistrettoPoint, points: &BitVec) -> Scalar {
let mut input = points.to_bytes().as_slice().to_vec();
let mut input = vec![];
input.push(GAMMA);
input.extend_from_slice(points.to_bytes().as_slice());
// enforce separation between ciphertext and u
input.extend_from_slice("|| u: ".as_bytes());
input.extend_from_slice(u.compress().as_bytes());
Scalar::hash_from_bytes::<Sha3_512>(input.as_slice())
}
@ -242,9 +254,9 @@ impl FuzzySecretKey {
/// 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(Clone, Debug, Serialize, Deserialize)]
pub struct FuzzyDetectionKey(Vec<Scalar>);
pub struct FuzzyDetectionKey<const GAMMA: u8>(Vec<Scalar>);
impl FuzzyDetectionKey {
impl<const GAMMA: u8> FuzzyDetectionKey<{ GAMMA }> {
/// a convenient id for a detection key for internal accounting purposes
/// do not expose this to applications
pub fn id(&self) -> String {
@ -256,18 +268,17 @@ impl FuzzyDetectionKey {
}
}
impl Display for FuzzyDetectionKey {
impl<const GAMMA: u8> Display for FuzzyDetectionKey<{ GAMMA }> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.id())
}
}
impl FuzzyDetectionKey {
impl<const GAMMA: u8> FuzzyDetectionKey<{ GAMMA }> {
/// calculate the ideal false positive rate of this detection key
/// ```
/// use fuzzytags::FuzzySecretKey;
/// let gamma = 24;
/// let secret_key = FuzzySecretKey::generate(gamma);
/// let secret_key = FuzzySecretKey::<24>::generate();
/// let public_key = secret_key.public_key();
/// // extract a detection key
/// let detection_key = secret_key.extract(5);
@ -281,8 +292,7 @@ impl FuzzyDetectionKey {
/// Example:
/// ```
/// use fuzzytags::FuzzySecretKey;
/// let gamma = 24;
/// let secret_key = FuzzySecretKey::generate(gamma);
/// let secret_key = FuzzySecretKey::<24>::generate();
/// let public_key = secret_key.public_key();
/// // extract a detection key
/// let detection_key = secret_key.extract(5);
@ -298,7 +308,7 @@ impl FuzzyDetectionKey {
/// // 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 {
pub fn test_tag(&self, tag: &FuzzyTag<{ GAMMA }>) -> bool {
// A few checks to make sure the tag is well formed.
// All zeros in u or y can lead to a tag that validates against *all* public keys
// That doesn't seem like a great idea, so we return false to be safe.
@ -307,7 +317,7 @@ impl FuzzyDetectionKey {
return false;
}
let m = FuzzySecretKey::g(tag.u, &tag.ciphertexts);
let m = FuzzySecretKey::<GAMMA>::g(tag.u, &tag.ciphertexts);
let g = RISTRETTO_BASEPOINT_POINT;
// Re-derive w = g^z from the public tag.
@ -324,7 +334,7 @@ impl FuzzyDetectionKey {
let mut result = true;
for (i, x_i) in self.0.iter().enumerate() {
// re-derive the key from the tag
let k_i = FuzzySecretKey::h(tag.u, tag.u.mul(x_i), w);
let k_i = FuzzySecretKey::<GAMMA>::h(tag.u, tag.u.mul(x_i), w);
// calculate the "original" plaintext
let c_i = match tag.ciphertexts.get(i) {
@ -346,9 +356,9 @@ impl FuzzyDetectionKey {
/// A public identity that others can create tags for.
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct FuzzyPublicKey(Vec<RistrettoPoint>);
pub struct FuzzyPublicKey<const GAMMA: u8>(Vec<RistrettoPoint>);
impl FuzzyPublicKey {
impl<const GAMMA: u8> FuzzyPublicKey<{ GAMMA }> {
/// a convenient id for a public key for internal accounting purposes
/// do not expose this to applications
pub fn id(&self) -> String {
@ -363,11 +373,11 @@ impl FuzzyPublicKey {
/// Example:
/// ```
/// use fuzzytags::{FuzzySecretKey};
/// let secret_key = FuzzySecretKey::generate(24);
/// let secret_key = FuzzySecretKey::<24>::generate();
/// let public_key = secret_key.public_key(); // give this to a sender
/// let tag = public_key.generate_tag();
/// ```
pub fn generate_tag(&self) -> FuzzyTag {
pub fn generate_tag(&self) -> FuzzyTag<{ GAMMA }> {
let mut rng = OsRng::default();
let g = RISTRETTO_BASEPOINT_POINT;
@ -380,7 +390,7 @@ impl FuzzyPublicKey {
// construct the ciphertext portion of the tag
let mut ciphertexts = BitVec::new();
for (_i, h_i) in self.0.iter().enumerate() {
let k_i = FuzzySecretKey::h(u, h_i.mul(r), w);
let k_i = FuzzySecretKey::<GAMMA>::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);
@ -401,7 +411,7 @@ impl FuzzyPublicKey {
// used to derive the key.
// finally calculate a `y` = 1/r * (z-m) which will be used to re-derive `w`
let m = FuzzySecretKey::g(u, &ciphertexts);
let m = FuzzySecretKey::<GAMMA>::g(u, &ciphertexts);
let y = r.invert().mul(z.sub(m));
return FuzzyTag { u, y, ciphertexts };
@ -414,8 +424,8 @@ impl FuzzyPublicKey {
/// Example:
/// ```
/// use fuzzytags::{FuzzySecretKey, FuzzyPublicKey};
/// let secret_key_1 = FuzzySecretKey::generate(24);
/// let secret_key_2 = FuzzySecretKey::generate(24);
/// let secret_key_1 = FuzzySecretKey::<24>::generate();
/// let secret_key_2 = FuzzySecretKey::<24>::generate();
/// let public_key_1 = secret_key_1.public_key(); // give this to a sender
/// let public_key_2 = secret_key_2.public_key(); // give this to a sender
/// // Will validate for detection keys derived from both secret_key_1 and secret_key_2 up
@ -423,7 +433,7 @@ impl FuzzyPublicKey {
/// // Sender can now do...tag will validate on detection keys of length 8 or lower.
/// let tag = FuzzyPublicKey::generate_entangled_tag(vec![public_key_1,public_key_2], 8);
/// ```
pub fn generate_entangled_tag(public_keys: Vec<FuzzyPublicKey>, length: usize) -> FuzzyTag {
pub fn generate_entangled_tag(public_keys: Vec<FuzzyPublicKey<{ GAMMA }>>, length: usize) -> FuzzyTag<{ GAMMA }> {
let mut rng = OsRng::default();
let g = RISTRETTO_BASEPOINT_POINT;
// generate some random points...
@ -445,10 +455,10 @@ impl FuzzyPublicKey {
let w = g.mul(z);
let mut key = vec![];
for (i, precompute) in public_key_precomputes[0].iter().enumerate() {
let k_i = FuzzySecretKey::h(u, *precompute, w);
let k_i = FuzzySecretKey::<GAMMA>::h(u, *precompute, w);
if i < length {
for precompute in public_key_precomputes.iter().skip(1) {
let n_k_i = FuzzySecretKey::h(u, precompute[i], w);
let n_k_i = FuzzySecretKey::<GAMMA>::h(u, precompute[i], w);
if k_i != n_k_i {
return None;
}
@ -466,7 +476,7 @@ impl FuzzyPublicKey {
}
// This is the same as generate_tag, kept separate to avoid over-decomposition
let m = FuzzySecretKey::g(u, &ciphertexts);
let m = FuzzySecretKey::<GAMMA>::g(u, &ciphertexts);
let y = r.invert().mul(z.sub(m));
return Some(FuzzyTag { u, y, ciphertexts });
};
@ -483,56 +493,52 @@ mod tests {
#[test]
fn test_compression() {
let gamma = 24;
let secret_key = FuzzySecretKey::generate(gamma);
let secret_key = FuzzySecretKey::<24>::generate();
let public_key = secret_key.public_key();
// Give public key to a another party...
// and then they can do...
let tag = public_key.generate_tag();
let compressed_tag = tag.compress();
let decompressed_tag = FuzzyTag::decompress(&compressed_tag).unwrap();
let decompressed_tag = FuzzyTag::<24>::decompress(&compressed_tag).unwrap();
assert_eq!(tag, decompressed_tag);
}
#[test]
fn test_serialization() {
// We support up to gamma=64 when deserializing..
for gamma in [5, 10, 15, 24, 45, 64].iter() {
// generate some new keys...
let secret_key = FuzzySecretKey::generate(*gamma);
let tag = secret_key.public_key.generate_tag();
// generate some new keys...
let secret_key = FuzzySecretKey::<15>::generate();
let tag = secret_key.public_key.generate_tag();
let detection_key = secret_key.extract(10);
let serialized_tag = serde_json::to_string(&tag).unwrap();
let deserialized_tag: FuzzyTag<15> = serde_json::from_str(&serialized_tag).unwrap();
assert_eq!(tag.compress(), deserialized_tag.compress());
assert_eq!(true, detection_key.test_tag(&deserialized_tag));
let detection_key = secret_key.extract(10);
// println!("{}", serde_json::to_string(&detection_key).unwrap());
// generate some new keys...
let secret_key = FuzzySecretKey::<24>::generate();
let tag = secret_key.public_key.generate_tag();
let detection_key = secret_key.extract(10);
let serialized_tag = serde_json::to_string(&tag).unwrap();
let deserialized_tag: FuzzyTag<24> = serde_json::from_str(&serialized_tag).unwrap();
assert_eq!(tag.compress(), deserialized_tag.compress());
assert_eq!(true, detection_key.test_tag(&deserialized_tag));
//println!("Original: {}", tag);
let serialized_tag = serde_json::to_string(&tag).unwrap();
//println!("Serialized: {}", serialized_tag);
let deserialized_tag: FuzzyTag = serde_json::from_str(&serialized_tag).unwrap();
// println!("Deserialized: {}", deserialized_tag);
// Test some equality and testing properties
assert_eq!(tag.compress(), deserialized_tag.compress());
assert_eq!(true, detection_key.test_tag(&deserialized_tag));
// Test some bincode...
let bincode_tag = bincode::serialize(&tag);
// println!("Serialized: {:?}", bincode_tag);
let deserialized_tag: FuzzyTag = bincode::deserialize(&bincode_tag.unwrap()).unwrap();
//println!("Deserialized: {}", deserialized_tag);
assert_eq!(tag.compress(), deserialized_tag.compress());
assert_eq!(true, detection_key.test_tag(&deserialized_tag));
}
// Test some bincode...
let bincode_tag = bincode::serialize(&tag);
// println!("Serialized: {:?}", bincode_tag);
let deserialized_tag: FuzzyTag<24> = bincode::deserialize(&bincode_tag.unwrap()).unwrap();
//println!("Deserialized: {}", deserialized_tag);
//assert_eq!(tag.compress(), deserialized_tag.compress());
assert_eq!(true, detection_key.test_tag(&deserialized_tag));
}
#[test]
#[cfg(feature = "entangled")]
fn test_multiple() {
use crate::FuzzyPublicKey;
let secret_keys: Vec<FuzzySecretKey> = (0..2).map(|_x| FuzzySecretKey::generate(24)).collect();
let public_keys: Vec<FuzzyPublicKey> = secret_keys.iter().map(|x| x.public_key()).collect();
let secret_keys: Vec<FuzzySecretKey<24>> = (0..2).map(|_x| FuzzySecretKey::<24>::generate()).collect();
let public_keys: Vec<FuzzyPublicKey<24>> = secret_keys.iter().map(|x| x.public_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 = FuzzyPublicKey::generate_entangled_tag(public_keys, 16);
println!("{}", entangled_tag);
@ -546,7 +552,7 @@ mod tests {
#[test]
fn correctness() {
let number_of_messages = 100;
let secret_key = FuzzySecretKey::generate(16);
let secret_key = FuzzySecretKey::<16>::generate();
for i in 0..number_of_messages {
let tag = secret_key.public_key().generate_tag();
println!("{}: {}", i, tag);
@ -554,20 +560,20 @@ mod tests {
}
}
fn gen_zero_tag_zero(max_gamma: usize) -> FuzzyTag {
fn gen_zero_tag_zero() -> FuzzyTag<24> {
let tag = FuzzyTag {
u: RistrettoPoint::default(),
y: Scalar::default(),
ciphertexts: BitVec::from_elem(max_gamma, false),
ciphertexts: BitVec::from_elem(24, false),
};
tag
}
fn gen_zero_tag_one(max_gamma: usize) -> FuzzyTag {
fn gen_zero_tag_one() -> FuzzyTag<24> {
let mut tag = FuzzyTag {
u: RistrettoPoint::default(),
y: Scalar::default(),
ciphertexts: BitVec::from_elem(max_gamma, false),
ciphertexts: BitVec::from_elem(24, false),
};
tag.ciphertexts.set_all();
tag
@ -579,21 +585,20 @@ mod tests {
// broadcast, which overall seems like a bad idea...
// Test to make sure that doesn't happen.
fn test_zero_tag() {
let secret_key = FuzzySecretKey::generate(24);
let tag = gen_zero_tag_zero(16);
let secret_key = FuzzySecretKey::<24>::generate();
let tag = gen_zero_tag_zero();
assert_eq!(false, secret_key.extract(6).test_tag(&tag));
let tag = gen_zero_tag_one(16);
let tag = gen_zero_tag_one();
assert_eq!(false, secret_key.extract(6).test_tag(&tag));
}
#[test]
fn false_positives() {
let gamma = 8;
let number_of_messages = 1000;
let secret_key = FuzzySecretKey::generate(gamma);
let secret_key = FuzzySecretKey::<24>::generate();
let mut false_positives = 0;
for _i in 0..number_of_messages {
let secret_key2 = FuzzySecretKey::generate(gamma);
let secret_key2 = FuzzySecretKey::<24>::generate();
let tag = secret_key2.public_key().generate_tag();
assert!(secret_key2.extract(3).test_tag(&tag));
if secret_key.extract(3).test_tag(&tag) == true {