Use a SeedableRng for CLSAG multisig signing

This commit is contained in:
Luke Parker 2022-04-28 17:12:54 -04:00
parent 20f214c300
commit 7ed1fca270
No known key found for this signature in database
GPG key ID: F9F1386DB1E119B6
4 changed files with 30 additions and 26 deletions

View file

@ -11,6 +11,7 @@ lazy_static = "1"
thiserror = "1" thiserror = "1"
rand_core = "0.6" rand_core = "0.6"
rand_chacha = { version = "0.3", optional = true }
tiny-keccak = { version = "2.0", features = ["keccak"] } tiny-keccak = { version = "2.0", features = ["keccak"] }
blake2 = "0.10" blake2 = "0.10"
@ -32,7 +33,7 @@ monero-epee-bin-serde = "1.0"
reqwest = { version = "0.11", features = ["json"] } reqwest = { version = "0.11", features = ["json"] }
[features] [features]
multisig = ["ff", "group", "dalek-ff-group", "frost"] multisig = ["ff", "group", "dalek-ff-group", "frost", "rand_chacha"]
[dev-dependencies] [dev-dependencies]
rand = "0.8" rand = "0.8"

View file

@ -1,6 +1,5 @@
use rand_core::{RngCore, CryptoRng}; use rand_core::{RngCore, CryptoRng};
use ff::Field;
use blake2::{Digest, Blake2b512};
use curve25519_dalek::{ use curve25519_dalek::{
constants::ED25519_BASEPOINT_TABLE, constants::ED25519_BASEPOINT_TABLE,
@ -29,8 +28,8 @@ mod multisig;
pub use multisig::Multisig; pub use multisig::Multisig;
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub(crate) fn sign_core( pub(crate) fn sign_core<R: RngCore + CryptoRng>(
rand_source: [u8; 64], rng: &mut R,
msg: &[u8; 32], msg: &[u8; 32],
input: &SignableInput, input: &SignableInput,
mask: Scalar, mask: Scalar,
@ -51,8 +50,6 @@ pub(crate) fn sign_core(
let z; 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(); C_out = Commitment::new(mask, input.commitment.amount).calculate();
@ -116,8 +113,7 @@ pub(crate) fn sign_core(
let mut s = vec![]; let mut s = vec![];
s.resize(n, Scalar::zero()); s.resize(n, Scalar::zero());
while i != r { while i != r {
s[i] = Scalar::from_bytes_mod_order_wide(&next_rand); s[i] = dalek_ff_group::Scalar::random(&mut *rng).0;
next_rand = Blake2b512::digest(&next_rand).as_slice().try_into().unwrap();
let c_p = mu_P * c; let c_p = mu_P * c;
let c_c = mu_C * c; let c_c = mu_C * c;
@ -176,7 +172,7 @@ pub fn sign<R: RngCore + CryptoRng>(
let mut rand_source = [0; 64]; let mut rand_source = [0; 64];
rng.fill_bytes(&mut rand_source); rng.fill_bytes(&mut rand_source);
let (mut clsag, c, mu_C, z, mu_P, C_out) = sign_core( let (mut clsag, c, mu_C, z, mu_P, C_out) = sign_core(
rand_source, rng,
&msg, &msg,
&inputs[i].1, &inputs[i].1,
mask, mask,

View file

@ -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::{ use curve25519_dalek::{
constants::ED25519_BASEPOINT_TABLE, constants::ED25519_BASEPOINT_TABLE,
@ -8,8 +9,9 @@ use curve25519_dalek::{
edwards::EdwardsPoint edwards::EdwardsPoint
}; };
use dalek_ff_group as dfg; use ff::Field;
use group::Group; use group::Group;
use dalek_ff_group as dfg;
use frost::{Curve, FrostError, algorithm::Algorithm, sign::ParamsView}; use frost::{Curve, FrostError, algorithm::Algorithm, sign::ParamsView};
use monero::util::ringct::{Key, Clsag}; use monero::util::ringct::{Key, Clsag};
@ -33,6 +35,7 @@ struct ClsagSignInterim {
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Multisig { pub struct Multisig {
seed: [u8; 32],
b: Vec<u8>, b: Vec<u8>,
AH: dfg::EdwardsPoint, AH: dfg::EdwardsPoint,
@ -43,12 +46,17 @@ pub struct Multisig {
} }
impl Multisig { impl Multisig {
pub fn new( pub fn new<R: RngCore + CryptoRng + SeedableRng>(
rng: &mut R,
msg: [u8; 32], msg: [u8; 32],
input: SignableInput input: SignableInput
) -> Result<Multisig, MultisigError> { ) -> Result<Multisig, MultisigError> {
let mut seed = [0; 32];
rng.fill_bytes(&mut seed);
Ok( Ok(
Multisig { Multisig {
seed,
b: vec![], b: vec![],
AH: dfg::EdwardsPoint::identity(), AH: dfg::EdwardsPoint::identity(),
@ -66,6 +74,7 @@ impl Algorithm<Ed25519> for Multisig {
fn context(&self) -> Vec<u8> { fn context(&self) -> Vec<u8> {
let mut context = vec![]; let mut context = vec![];
context.extend(&self.seed);
context.extend(&self.msg); context.extend(&self.msg);
context.extend(&self.input.context()); context.extend(&self.input.context());
context context
@ -140,20 +149,16 @@ impl Algorithm<Ed25519> for Multisig {
) -> dfg::Scalar { ) -> dfg::Scalar {
// Use everyone's commitments to derive a random source all signers can agree upon // 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 // Cannot be manipulated to effect and all signers must, and will, know this
let mut rand_source = Blake2b512::new() // Uses a parent seed (part of context) as well just to enable further privacy options
.chain("clsag_randomness") let mut seed = b"CLSAG_randomness".to_vec();
.chain(&self.b) seed.extend(&self.context());
.finalize() seed.extend(&self.b);
.as_slice() let mut rng = ChaCha12Rng::from_seed(Blake2b512::digest(seed)[0 .. 32].try_into().unwrap());
.try_into() let mask = dfg::Scalar::random(&mut rng).0;
.unwrap();
let mask = Scalar::from_bytes_mod_order_wide(&rand_source);
rand_source = Blake2b512::digest(&rand_source).as_slice().try_into().unwrap();
#[allow(non_snake_case)] #[allow(non_snake_case)]
let (clsag, c, mu_C, z, mu_P, C_out) = sign_core( let (clsag, c, mu_C, z, mu_P, C_out) = sign_core(
rand_source, &mut rng,
&self.msg, &self.msg,
&self.input, &self.input,
mask, mask,

View file

@ -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}; use curve25519_dalek::{constants::ED25519_BASEPOINT_TABLE, scalar::Scalar};
@ -110,6 +111,7 @@ fn test_multisig() -> Result<(), MultisigError> {
sign::StateMachine::new( sign::StateMachine::new(
sign::Params::new( sign::Params::new(
clsag::Multisig::new( clsag::Multisig::new(
&mut ChaCha12Rng::seed_from_u64(1),
msg, msg,
SignableInput::new(image, vec![], ring.clone(), RING_INDEX, Commitment::new(randomness, AMOUNT)).unwrap() SignableInput::new(image, vec![], ring.clone(), RING_INDEX, Commitment::new(randomness, AMOUNT)).unwrap()
).unwrap(), ).unwrap(),