diff --git a/coins/monero/Cargo.toml b/coins/monero/Cargo.toml index 418ebc3f..7732e74b 100644 --- a/coins/monero/Cargo.toml +++ b/coins/monero/Cargo.toml @@ -11,6 +11,7 @@ lazy_static = "1" thiserror = "1" rand_core = "0.6" +rand_chacha = { version = "0.3", optional = true } tiny-keccak = { version = "2.0", features = ["keccak"] } blake2 = "0.10" @@ -32,7 +33,7 @@ monero-epee-bin-serde = "1.0" reqwest = { version = "0.11", features = ["json"] } [features] -multisig = ["ff", "group", "dalek-ff-group", "frost"] +multisig = ["ff", "group", "dalek-ff-group", "frost", "rand_chacha"] [dev-dependencies] rand = "0.8" diff --git a/coins/monero/src/clsag/mod.rs b/coins/monero/src/clsag/mod.rs index 0c478ad2..d2c0dcb0 100644 --- a/coins/monero/src/clsag/mod.rs +++ b/coins/monero/src/clsag/mod.rs @@ -1,6 +1,5 @@ use rand_core::{RngCore, CryptoRng}; - -use blake2::{Digest, Blake2b512}; +use ff::Field; use curve25519_dalek::{ constants::ED25519_BASEPOINT_TABLE, @@ -29,8 +28,8 @@ mod multisig; pub use multisig::Multisig; #[allow(non_snake_case)] -pub(crate) fn sign_core( - rand_source: [u8; 64], +pub(crate) fn sign_core( + rng: &mut R, msg: &[u8; 32], input: &SignableInput, mask: Scalar, @@ -51,8 +50,6 @@ pub(crate) fn sign_core( let z; - let mut next_rand = rand_source; - next_rand = Blake2b512::digest(&next_rand).as_slice().try_into().unwrap(); { C_out = Commitment::new(mask, input.commitment.amount).calculate(); @@ -116,8 +113,7 @@ pub(crate) fn sign_core( let mut s = vec![]; s.resize(n, Scalar::zero()); while i != r { - s[i] = Scalar::from_bytes_mod_order_wide(&next_rand); - next_rand = Blake2b512::digest(&next_rand).as_slice().try_into().unwrap(); + s[i] = dalek_ff_group::Scalar::random(&mut *rng).0; let c_p = mu_P * c; let c_c = mu_C * c; @@ -176,7 +172,7 @@ pub fn sign( let mut rand_source = [0; 64]; rng.fill_bytes(&mut rand_source); let (mut clsag, c, mu_C, z, mu_P, C_out) = sign_core( - rand_source, + rng, &msg, &inputs[i].1, mask, diff --git a/coins/monero/src/clsag/multisig.rs b/coins/monero/src/clsag/multisig.rs index 005b483d..423e94cf 100644 --- a/coins/monero/src/clsag/multisig.rs +++ b/coins/monero/src/clsag/multisig.rs @@ -1,6 +1,7 @@ -use rand_core::{RngCore, CryptoRng}; +use rand_core::{RngCore, CryptoRng, SeedableRng}; +use rand_chacha::ChaCha12Rng; -use blake2::{digest::Update, Digest, Blake2b512}; +use blake2::{Digest, Blake2b512}; use curve25519_dalek::{ constants::ED25519_BASEPOINT_TABLE, @@ -8,8 +9,9 @@ use curve25519_dalek::{ edwards::EdwardsPoint }; -use dalek_ff_group as dfg; +use ff::Field; use group::Group; +use dalek_ff_group as dfg; use frost::{Curve, FrostError, algorithm::Algorithm, sign::ParamsView}; use monero::util::ringct::{Key, Clsag}; @@ -33,6 +35,7 @@ struct ClsagSignInterim { #[allow(non_snake_case)] #[derive(Clone, Debug)] pub struct Multisig { + seed: [u8; 32], b: Vec, AH: dfg::EdwardsPoint, @@ -43,12 +46,17 @@ pub struct Multisig { } impl Multisig { - pub fn new( + pub fn new( + rng: &mut R, msg: [u8; 32], input: SignableInput ) -> Result { + let mut seed = [0; 32]; + rng.fill_bytes(&mut seed); + Ok( Multisig { + seed, b: vec![], AH: dfg::EdwardsPoint::identity(), @@ -66,6 +74,7 @@ impl Algorithm for Multisig { fn context(&self) -> Vec { let mut context = vec![]; + context.extend(&self.seed); context.extend(&self.msg); context.extend(&self.input.context()); context @@ -140,20 +149,16 @@ impl Algorithm for Multisig { ) -> dfg::Scalar { // Use everyone's commitments to derive a random source all signers can agree upon // Cannot be manipulated to effect and all signers must, and will, know this - let mut rand_source = Blake2b512::new() - .chain("clsag_randomness") - .chain(&self.b) - .finalize() - .as_slice() - .try_into() - .unwrap(); - - let mask = Scalar::from_bytes_mod_order_wide(&rand_source); - rand_source = Blake2b512::digest(&rand_source).as_slice().try_into().unwrap(); + // Uses a parent seed (part of context) as well just to enable further privacy options + let mut seed = b"CLSAG_randomness".to_vec(); + seed.extend(&self.context()); + seed.extend(&self.b); + let mut rng = ChaCha12Rng::from_seed(Blake2b512::digest(seed)[0 .. 32].try_into().unwrap()); + let mask = dfg::Scalar::random(&mut rng).0; #[allow(non_snake_case)] let (clsag, c, mu_C, z, mu_P, C_out) = sign_core( - rand_source, + &mut rng, &self.msg, &self.input, mask, diff --git a/coins/monero/tests/clsag.rs b/coins/monero/tests/clsag.rs index 83692a4b..361bb320 100644 --- a/coins/monero/tests/clsag.rs +++ b/coins/monero/tests/clsag.rs @@ -1,4 +1,5 @@ -use rand::{RngCore, rngs::OsRng}; +use rand::{RngCore, SeedableRng, rngs::OsRng}; +use rand_chacha::ChaCha12Rng; use curve25519_dalek::{constants::ED25519_BASEPOINT_TABLE, scalar::Scalar}; @@ -110,6 +111,7 @@ fn test_multisig() -> Result<(), MultisigError> { sign::StateMachine::new( sign::Params::new( clsag::Multisig::new( + &mut ChaCha12Rng::seed_from_u64(1), msg, SignableInput::new(image, vec![], ring.clone(), RING_INDEX, Commitment::new(randomness, AMOUNT)).unwrap() ).unwrap(),