diff --git a/common/dkg/Cargo.toml b/common/dkg/Cargo.toml index 58e899d7b37..b8e4f557319 100644 --- a/common/dkg/Cargo.toml +++ b/common/dkg/Cargo.toml @@ -17,7 +17,6 @@ nym-contracts-common = { path = "../cosmwasm-smart-contracts/contracts-common", bs58 = { workspace = true } -lazy_static = { workspace = true } rand = { workspace = true } rand_chacha = { workspace = true } rand_core = { workspace = true } diff --git a/common/dkg/src/bte/encryption.rs b/common/dkg/src/bte/encryption.rs index 81b304bc7b0..438192757fa 100644 --- a/common/dkg/src/bte/encryption.rs +++ b/common/dkg/src/bte/encryption.rs @@ -13,9 +13,9 @@ use rand::CryptoRng; use rand_core::RngCore; use std::collections::HashMap; use std::ops::Neg; -use zeroize::Zeroize; +use zeroize::{Zeroize, ZeroizeOnDrop}; -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)] pub struct Ciphertexts { pub rr: [G1Projective; NUM_CHUNKS], pub ss: [G1Projective; NUM_CHUNKS], @@ -164,8 +164,7 @@ impl Ciphertexts { } } -#[derive(Zeroize)] -#[zeroize(drop)] +#[derive(Zeroize, ZeroizeOnDrop)] /// Randomness generated during ciphertext generation that is required for proofs of knowledge. /// /// It must be handled with extreme care as its misuse might help malicious parties to recover @@ -399,7 +398,7 @@ pub fn baby_step_giant_step( #[cfg(test)] mod tests { use super::*; - use crate::bte::{keygen, setup, DEFAULT_BSGS_TABLE}; + use crate::bte::{keygen, setup, BSGS_TABLE}; use rand_core::SeedableRng; fn verify_hazmat_rand(ciphertext: &Ciphertexts, randomness: &HazmatRandomness) { @@ -457,8 +456,6 @@ mod tests { let (decryption_key1, public_key1) = keygen(¶ms, &mut rng); let (decryption_key2, public_key2) = keygen(¶ms, &mut rng); - let lookup_table = &DEFAULT_BSGS_TABLE; - for _ in 0..10 { let m1 = Share::random(&mut rng); let m2 = Share::random(&mut rng); @@ -467,22 +464,12 @@ mod tests { let (ciphertext, hazmat) = encrypt_shares(shares, ¶ms, &mut rng); verify_hazmat_rand(&ciphertext, &hazmat); - let recovered1 = decrypt_share( - ¶ms, - &decryption_key1, - 0, - &ciphertext, - Some(lookup_table), - ) - .unwrap(); - let recovered2 = decrypt_share( - ¶ms, - &decryption_key2, - 1, - &ciphertext, - Some(lookup_table), - ) - .unwrap(); + let recovered1 = + decrypt_share(¶ms, &decryption_key1, 0, &ciphertext, Some(&BSGS_TABLE)) + .unwrap(); + let recovered2 = + decrypt_share(¶ms, &decryption_key2, 1, &ciphertext, Some(&BSGS_TABLE)) + .unwrap(); assert_eq!(m1, recovered1); assert_eq!(m2, recovered2); } @@ -498,8 +485,6 @@ mod tests { let (decryption_key1, public_key1) = keygen(¶ms, &mut rng); let (decryption_key2, public_key2) = keygen(¶ms, &mut rng); - let lookup_table = &DEFAULT_BSGS_TABLE; - for _ in 0..10 { let m1 = Share::random(&mut rng); let m2 = Share::random(&mut rng); @@ -508,22 +493,12 @@ mod tests { let (ciphertext, hazmat) = encrypt_shares(shares, ¶ms, &mut rng); verify_hazmat_rand(&ciphertext, &hazmat); - let recovered1 = decrypt_share( - ¶ms, - &decryption_key1, - 0, - &ciphertext, - Some(lookup_table), - ) - .unwrap(); - let recovered2 = decrypt_share( - ¶ms, - &decryption_key2, - 1, - &ciphertext, - Some(lookup_table), - ) - .unwrap(); + let recovered1 = + decrypt_share(¶ms, &decryption_key1, 0, &ciphertext, Some(&BSGS_TABLE)) + .unwrap(); + let recovered2 = + decrypt_share(¶ms, &decryption_key2, 1, &ciphertext, Some(&BSGS_TABLE)) + .unwrap(); assert_eq!(m1, recovered1); assert_eq!(m2, recovered2); } diff --git a/common/dkg/src/bte/keys.rs b/common/dkg/src/bte/keys.rs index 20d896a547b..b81d6cbf778 100644 --- a/common/dkg/src/bte/keys.rs +++ b/common/dkg/src/bte/keys.rs @@ -11,7 +11,7 @@ use group::GroupEncoding; use nym_pemstore::traits::{PemStorableKey, PemStorableKeyPair}; use rand::CryptoRng; use rand_core::RngCore; -use zeroize::Zeroize; +use zeroize::{Zeroize, ZeroizeOnDrop}; // produces public key and a decryption key for the root of the tree pub fn keygen( @@ -48,7 +48,7 @@ pub fn keygen( (dk, key_with_proof) } -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Copy, PartialEq, Eq, Zeroize)] pub struct PublicKey(pub(crate) G1Projective); impl PublicKey { @@ -57,7 +57,7 @@ impl PublicKey { } } -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)] pub struct PublicKeyWithProof { pub(crate) key: PublicKey, pub(crate) proof: ProofOfDiscreteLog, @@ -136,8 +136,7 @@ impl PublicKeyWithProof { } } -#[derive(Debug, Zeroize)] -#[zeroize(drop)] +#[derive(Debug, Zeroize, ZeroizeOnDrop)] #[cfg_attr(test, derive(PartialEq, Eq))] pub struct DecryptionKey { // g1^rho @@ -242,6 +241,7 @@ impl DecryptionKey { } } +#[derive(Zeroize, ZeroizeOnDrop)] pub struct KeyPair { pub(crate) private_key: DecryptionKey, pub(crate) public_key: PublicKeyWithProof, diff --git a/common/dkg/src/bte/mod.rs b/common/dkg/src/bte/mod.rs index 0bb18dc0828..ea5c9a70c6f 100644 --- a/common/dkg/src/bte/mod.rs +++ b/common/dkg/src/bte/mod.rs @@ -1,11 +1,13 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 +use std::sync::LazyLock; + +use crate::bte::encryption::BabyStepGiantStepLookup; use crate::utils::hash_g2; use crate::{Chunk, Share}; use bls12_381::{G1Affine, G2Affine, G2Prepared, G2Projective, Gt}; use group::Curve; -use lazy_static::lazy_static; pub mod encryption; pub mod keys; @@ -16,14 +18,12 @@ pub mod proof_sharing; pub use encryption::{decrypt_share, encrypt_shares, Ciphertexts}; pub use keys::{keygen, DecryptionKey, PublicKey, PublicKeyWithProof}; -lazy_static! { - pub(crate) static ref PAIRING_BASE: Gt = - bls12_381::pairing(&G1Affine::generator(), &G2Affine::generator()); - pub(crate) static ref G2_GENERATOR_PREPARED: G2Prepared = - G2Prepared::from(G2Affine::generator()); - pub(crate) static ref DEFAULT_BSGS_TABLE: encryption::BabyStepGiantStepLookup = - encryption::BabyStepGiantStepLookup::default(); -} +pub(crate) static PAIRING_BASE: LazyLock = + LazyLock::new(|| bls12_381::pairing(&G1Affine::generator(), &G2Affine::generator())); +pub(crate) static G2_GENERATOR_PREPARED: LazyLock = + LazyLock::new(|| G2Prepared::from(G2Affine::generator())); +pub static BSGS_TABLE: LazyLock = + LazyLock::new(BabyStepGiantStepLookup::default); // Domain tries to follow guidelines specified by: // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1 diff --git a/common/dkg/src/bte/proof_chunking.rs b/common/dkg/src/bte/proof_chunking.rs index 2da6e83b334..7e5b5cec2f3 100644 --- a/common/dkg/src/bte/proof_chunking.rs +++ b/common/dkg/src/bte/proof_chunking.rs @@ -12,6 +12,7 @@ use ff::Field; use group::{Group, GroupEncoding}; use rand::{CryptoRng, Rng}; use rand_core::{RngCore, SeedableRng}; +use zeroize::{Zeroize, ZeroizeOnDrop}; const CHUNKING_ORACLE_DOMAIN: &[u8] = b"NYM_COCONUT_NIDKG_V01_CS01_SHA-256_CHACHA20_CHUNKING_ORACLE"; @@ -67,7 +68,7 @@ impl<'a> Instance<'a> { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)] pub struct ProofOfChunking { y0: G1Projective, bb: Vec, diff --git a/common/dkg/src/bte/proof_discrete_log.rs b/common/dkg/src/bte/proof_discrete_log.rs index 3956e3837dd..de186f8fb6c 100644 --- a/common/dkg/src/bte/proof_discrete_log.rs +++ b/common/dkg/src/bte/proof_discrete_log.rs @@ -7,14 +7,14 @@ use ff::Field; use group::GroupEncoding; use rand::CryptoRng; use rand_core::RngCore; -use zeroize::Zeroize; +use zeroize::{Zeroize, ZeroizeOnDrop}; // Domain tries to follow guidelines specified by: // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1 const DISCRETE_LOG_DOMAIN: &[u8] = b"NYM_COCONUT_NIDKG_V01_CS01_WITH_BLS12381_XMD:SHA-256_SSWU_RO_PROOF_DISCRETE_LOG"; -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)] pub struct ProofOfDiscreteLog { pub(crate) rand_commitment: G1Projective, pub(crate) response: Scalar, @@ -52,9 +52,9 @@ impl ProofOfDiscreteLog { let public_bytes = public.to_bytes(); let rand_commit_bytes = rand_commit.to_bytes(); - let mut bytes = Vec::with_capacity(96); - bytes.extend_from_slice(public_bytes.as_ref()); - bytes.extend_from_slice(rand_commit_bytes.as_ref()); + let mut bytes = [0u8; 96]; + bytes[0..48].copy_from_slice(public_bytes.as_ref()); + bytes[48..96].copy_from_slice(rand_commit_bytes.as_ref()); hash_to_scalar(bytes, DISCRETE_LOG_DOMAIN) } diff --git a/common/dkg/src/bte/proof_sharing.rs b/common/dkg/src/bte/proof_sharing.rs index fe088c772fd..5659ec92350 100644 --- a/common/dkg/src/bte/proof_sharing.rs +++ b/common/dkg/src/bte/proof_sharing.rs @@ -12,6 +12,7 @@ use group::GroupEncoding; use rand::CryptoRng; use rand_core::RngCore; use std::collections::BTreeMap; +use zeroize::{Zeroize, ZeroizeOnDrop}; // Domain tries to follow guidelines specified by: // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-11#section-3.1 @@ -77,7 +78,7 @@ impl<'a> Instance<'a> { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)] pub struct ProofOfSecretSharing { ff: G1Projective, aa: G2Projective, diff --git a/common/dkg/src/dealing.rs b/common/dkg/src/dealing.rs index e9a96886c20..832e1260ff7 100644 --- a/common/dkg/src/dealing.rs +++ b/common/dkg/src/dealing.rs @@ -18,7 +18,7 @@ use rand_core::RngCore; use std::collections::BTreeMap; use zeroize::Zeroize; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Zeroize)] #[cfg_attr(test, derive(PartialEq, Eq))] pub struct RecoveredVerificationKeys { pub recovered_master: G2Projective, @@ -83,7 +83,7 @@ impl RecoveredVerificationKeys { } } -#[derive(Debug, Clone, PartialEq, Eq)] +#[derive(Debug, Clone, PartialEq, Eq, Zeroize)] pub struct Dealing { pub public_coefficients: PublicCoefficients, pub ciphertexts: Ciphertexts, diff --git a/common/dkg/src/interpolation/polynomial.rs b/common/dkg/src/interpolation/polynomial.rs index f3874806e1f..b6a2331c130 100644 --- a/common/dkg/src/interpolation/polynomial.rs +++ b/common/dkg/src/interpolation/polynomial.rs @@ -9,9 +9,9 @@ use group::GroupEncoding; use rand::CryptoRng; use rand_core::RngCore; use std::ops::{Add, Index, IndexMut}; -use zeroize::Zeroize; +use zeroize::{Zeroize, ZeroizeOnDrop}; -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)] pub struct PublicCoefficients { pub(crate) coefficients: Vec, } @@ -111,8 +111,7 @@ impl IndexMut for PublicCoefficients { } } -#[derive(Clone, Debug, PartialEq, Eq, Zeroize)] -#[zeroize(drop)] +#[derive(Clone, Debug, PartialEq, Eq, Zeroize, ZeroizeOnDrop)] pub struct Polynomial { coefficients: Vec, } diff --git a/common/dkg/src/share.rs b/common/dkg/src/share.rs index a108a064ae9..96039048be4 100644 --- a/common/dkg/src/share.rs +++ b/common/dkg/src/share.rs @@ -6,14 +6,13 @@ use crate::error::DkgError; use crate::interpolation::perform_lagrangian_interpolation_at_origin; use crate::NodeIndex; use bls12_381::Scalar; -use zeroize::Zeroize; +use zeroize::{Zeroize, ZeroizeOnDrop}; // if this type is changed, one must ensure all values can fit in it pub type Chunk = u16; -#[derive(PartialEq, Eq, Debug, Zeroize)] +#[derive(PartialEq, Eq, Debug, Zeroize, ZeroizeOnDrop)] #[cfg_attr(test, derive(Clone))] -#[zeroize(drop)] pub struct Share(pub(crate) Scalar); pub fn combine_shares(shares: Vec, node_indices: &[NodeIndex]) -> Result { @@ -66,9 +65,8 @@ impl From for Share { } } -#[derive(Default, Zeroize)] +#[derive(Default, Zeroize, ZeroizeOnDrop)] #[cfg_attr(test, derive(Clone))] -#[zeroize(drop)] pub(crate) struct ChunkedShare { pub(crate) chunks: [Chunk; NUM_CHUNKS], }