diff --git a/Cargo.lock b/Cargo.lock index fc6ec2d..b0239db 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -187,6 +187,7 @@ dependencies = [ "rustc_version", "serde", "subtle", + "zeroize", ] [[package]] @@ -366,6 +367,7 @@ dependencies = [ "serde", "sha2", "subtle", + "zeroize", ] [[package]] @@ -780,3 +782,23 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/Cargo.toml b/Cargo.toml index bf5fca3..f953b9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,4 @@ rand_core = { version = "0.6", default-features = false } serde = { version = "1.0.217", default-features = false } sha2 = { version = "0.10.8", default-features = false } subtle = { version = "2.6.1", default-features = false } +zeroize = { version = "1.8.1", default-features = false } diff --git a/Makefile b/Makefile index 389b94b..13e5d7d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -ALL_FEATURES := serde,random-flag-ciphertexts +ALL_FEATURES := serde,random-flag-ciphertexts,zeroize .PHONY: all all: clippy-no-std-all-features diff --git a/polyfuzzy/Cargo.toml b/polyfuzzy/Cargo.toml index 71b1fc1..9524a2a 100644 --- a/polyfuzzy/Cargo.toml +++ b/polyfuzzy/Cargo.toml @@ -12,6 +12,7 @@ edition = "2021" serde = ["dep:serde", "curve25519-dalek/serde"] sha2-force-soft = ["sha2/force-soft"] random-flag-ciphertexts = [] +zeroize = ["dep:zeroize", "curve25519-dalek/zeroize"] [dependencies] curve25519-dalek = { workspace = true, features = ["rand_core"] } @@ -19,6 +20,7 @@ rand_core = { workspace = true } serde = { workspace = true, features = ["derive", "alloc"], optional = true } sha2 = { workspace = true } subtle = { workspace = true } +zeroize = { workspace = true, features = ["alloc", "derive"], optional = true } [dev-dependencies] criterion = { workspace = true } diff --git a/polyfuzzy/src/fmd2_compact/mod.rs b/polyfuzzy/src/fmd2_compact/mod.rs index 97b8b92..1bce2a8 100644 --- a/polyfuzzy/src/fmd2_compact/mod.rs +++ b/polyfuzzy/src/fmd2_compact/mod.rs @@ -9,6 +9,8 @@ use polynomial::{EncodedPolynomial, PointEvaluations, Polynomial}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use subtle::ConstantTimeEq; +#[cfg(feature = "zeroize")] +use zeroize::Zeroize; mod polynomial; use crate::{ @@ -21,7 +23,8 @@ use crate::{ /// A polynomial over the scalar field of Ristretto of degree = `t` (the threshold parameter). #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct CompactSecretKey(Polynomial); +#[cfg_attr(feature = "zeroize", derive(Zeroize))] +pub struct CompactSecretKey(#[cfg_attr(feature = "zeroize", zeroize)] Polynomial); impl CompactSecretKey { /// Get the public key counterpart of this key @@ -233,11 +236,10 @@ impl MultiFmdScheme for MultiFmd2CompactSchem basepoint_eg: expanded_pk_ref.randomized_key.0.basepoint, keys: expanded_pk_ref.randomized_key.0.results.clone(), }; - let trapdoor = Scalar::random(rng); let flag = FlagCiphertexts(GenericFlagCiphertexts::generate_flag( &gpk, - &ChamaleonHashBasepoint::new(&gpk, &trapdoor), + &ChamaleonHashBasepoint::new(rng, &gpk), rng, )); diff --git a/polyfuzzy/src/fmd2_compact/polynomial.rs b/polyfuzzy/src/fmd2_compact/polynomial.rs index aacafca..cb3e3ff 100644 --- a/polyfuzzy/src/fmd2_compact/polynomial.rs +++ b/polyfuzzy/src/fmd2_compact/polynomial.rs @@ -3,11 +3,15 @@ use alloc::vec::Vec; use curve25519_dalek::{RistrettoPoint, Scalar}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "zeroize")] +use zeroize::Zeroize; /// A degree `t` polynomial p(X) in Z_q[X] given by its t+1 coefficients. #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "zeroize", derive(Zeroize))] pub(crate) struct Polynomial { + #[cfg_attr(feature = "zeroize", zeroize)] coeffs: Vec, } @@ -22,7 +26,9 @@ pub(crate) struct EncodedPolynomial { /// γ scalar evaluations of the polynomial p(X) at public scalars. /// result[i] = p(public_scalar[i]) #[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "zeroize", derive(Zeroize))] pub(crate) struct ScalarEvaluations { + #[cfg_attr(feature = "zeroize", zeroize)] pub(crate) results: Vec, } diff --git a/polyfuzzy/src/fmd2_generic.rs b/polyfuzzy/src/fmd2_generic.rs index e10a690..fa21b00 100644 --- a/polyfuzzy/src/fmd2_generic.rs +++ b/polyfuzzy/src/fmd2_generic.rs @@ -12,6 +12,8 @@ use rand_core::{CryptoRng, RngCore}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256, Sha512}; +#[cfg(feature = "zeroize")] +use zeroize::{Zeroize, Zeroizing}; /// Compressed representation of the γ bit-ciphertexts of a [`GenericFlagCiphertexts`]. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -57,8 +59,9 @@ impl CiphertextBits { #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "zeroize", derive(Zeroize))] /// γ secret subkeys (scalars). For minimum false-positive rate p:=2^{-γ}. -pub struct FmdSecretKey(pub(crate) Vec); +pub struct FmdSecretKey(#[cfg_attr(feature = "zeroize", zeroize)] pub(crate) Vec); impl FmdSecretKey { pub(crate) fn generate_keys(gamma: usize, rng: &mut R) -> Self { @@ -137,9 +140,11 @@ impl FmdSecretKey { #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "zeroize", derive(Zeroize))] /// A subset of n-out-γ secret subkeys, and the positions /// they occupy in [FmdSecretKey]. pub struct DetectionKey { + #[cfg_attr(feature = "zeroize", zeroize)] pub(crate) subkeys: Vec, pub(crate) indices: Vec, @@ -200,16 +205,41 @@ pub(crate) struct GenericFmdPublicKey { } #[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "zeroize", derive(Zeroize))] pub(crate) struct ChamaleonHashBasepoint { - base: RistrettoPoint, // Basepoint for the Chamaleon Hash. - dlog: Scalar, // Discrete log of `basepoint_ch` in base `GenericPublicKey.basepoint_eg`. + /// Basepoint for the Chamaleon Hash. + base: RistrettoPoint, + /// Discrete log of `basepoint_ch` in base `GenericPublicKey.basepoint_eg`. + #[cfg_attr(feature = "zeroize", zeroize)] + dlog: Scalar, } +#[cfg(feature = "zeroize")] +type NewChamaleonHashBasepoint = Zeroizing; + +#[cfg(not(feature = "zeroize"))] +type NewChamaleonHashBasepoint = ChamaleonHashBasepoint; + impl ChamaleonHashBasepoint { - pub(crate) fn new(pk: &GenericFmdPublicKey, dlog: &Scalar) -> ChamaleonHashBasepoint { - ChamaleonHashBasepoint { + pub(crate) fn new( + rng: &mut R, + pk: &GenericFmdPublicKey, + ) -> NewChamaleonHashBasepoint { + let dlog = Scalar::random(rng); + + let hash = ChamaleonHashBasepoint { base: pk.basepoint_eg * dlog, - dlog: *dlog, + dlog, + }; + + #[cfg(feature = "zeroize")] + { + Zeroizing::new(hash) + } + + #[cfg(not(feature = "zeroize"))] + { + hash } } }