Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Defne public interface for distributed schnorr signature scheme #71

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions src/crypto/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1 @@
pub mod multi_party_schnorr;

#[cfg(test)]
mod test_multi_party_schnorr;
157 changes: 157 additions & 0 deletions src/crypto/multi_party_schnorr/mock_impl.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
use crate::crypto::multi_party_schnorr::traits::key_generation_protocol::{
KeyGenerationProtocol, NodeShare, NodeVSS,
};
use crate::crypto::multi_party_schnorr::traits::signature_issuing_protocol::{
BlockShare, BlockVSS, LocalSig, SignatureIssuingProtocol,
};
use crate::crypto::multi_party_schnorr::traits::{Error, Secret, Signature};
use secp256k1::rand::prelude::ThreadRng;
use secp256k1::rand::thread_rng;
use secp256k1::{PublicKey, SecretKey};
use std::collections::hash_map::RandomState;
use std::collections::HashSet;
use std::str::FromStr;

struct MockImpl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This struct should be public.


fn random_pubkey() -> PublicKey {
let secp = secp256k1::Secp256k1::new();
PublicKey::from_secret_key(&secp, &SecretKey::new(&mut thread_rng()))
}

fn random_secret() -> Secret {
Secret::from(SecretKey::new(&mut thread_rng()))
}

impl KeyGenerationProtocol for MockImpl {
fn create_node_vss(
node_private_key: &SecretKey,
signer_keys: &Vec<PublicKey>,
threshold: usize,
) -> HashSet<NodeVSS, RandomState> {
let vss = NodeVSS {
sender_pubkey: random_pubkey(),
receiver_pubkey: random_pubkey(),
commitments: vec![],
secret: random_secret(),
};
let mut set = HashSet::new();
set.insert(vss);
set
}

fn verify_node_vss(vss: &NodeVSS) -> Result<(), Error> {
Ok(())
}

fn aggregate_node_vss(vss_set: &HashSet<NodeVSS, RandomState>) -> NodeShare {
NodeShare {
aggregated_pubkey: random_pubkey(),
secret_share: random_secret(),
}
}
}

impl SignatureIssuingProtocol for MockImpl {
fn create_block_vss(
signer_keys: &Vec<PublicKey>,
threshold: usize,
) -> HashSet<BlockVSS, RandomState> {
let vss = BlockVSS {
sender_pubkey: random_pubkey(),
receiver_pubkey: random_pubkey(),
positive_commitments: vec![],
positive_secret: random_secret(),
negative_commitments: vec![],
negative_secret: random_secret(),
};
let mut set = HashSet::new();
set.insert(vss);
set
}

fn verify_block_vss(vss: &BlockVSS) -> Result<(), Error> {
Ok(())
}

fn aggregate_block_vss(vss_set: &HashSet<BlockVSS, RandomState>) -> BlockShare {
BlockShare {
aggregated_pubkey: random_pubkey(),
positive_secret_share: random_secret(),
negative_secret_share: random_secret(),
}
}

fn create_local_sig(
message: &[u8; 32],
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use Message type.

node_share: &NodeShare,
block_share: &BlockShare,
) -> LocalSig {
LocalSig {
signer_pubkey: random_pubkey(),
gamma_i: random_secret(),
}
}

fn verify_local_sig(
local_sig: &LocalSig,
node_vss_set: &HashSet<NodeVSS, RandomState>,
block_vss_set: &HashSet<BlockVSS, RandomState>,
) -> Result<(), Error> {
Ok(())
}

fn compute_final_signature(
local_sigs: &HashSet<LocalSig, RandomState>,
threshold: usize,
) -> Result<Signature, Error> {
Ok(Signature {
r_x: [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
],
sigma: [
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
],
})
}
}

#[cfg(test)]
mod tests {
use crate::crypto::multi_party_schnorr::mock_impl::MockImpl;
use crate::crypto::multi_party_schnorr::traits::key_generation_protocol::KeyGenerationProtocol;
use crate::crypto::multi_party_schnorr::traits::signature_issuing_protocol::SignatureIssuingProtocol;
use crate::tests::helper::keys::TEST_KEYS;
use secp256k1::PublicKey;
use std::collections::HashSet;

#[test]
fn test() {
let signer_keys = TEST_KEYS
.pubkeys()
.into_iter()
.map(|i| i.key)
.collect::<Vec<PublicKey>>();
let node_vss_set = MockImpl::create_node_vss(&TEST_KEYS.key[0].key, &signer_keys, 3);
for vss in node_vss_set.iter() {
MockImpl::verify_node_vss(vss);
}
let node_share = MockImpl::aggregate_node_vss(&node_vss_set);

let block_vss_set = MockImpl::create_block_vss(&signer_keys, 3);
for vss in block_vss_set.iter() {
MockImpl::verify_block_vss(vss);
}
let block_share = MockImpl::aggregate_block_vss(&block_vss_set);
let message = [0u8; 32];
let local_sig = MockImpl::create_local_sig(&message, &node_share, &block_share);
MockImpl::verify_local_sig(&local_sig, &node_vss_set, &block_vss_set);
let mut local_sigs = HashSet::new();
local_sigs.insert(local_sig);
MockImpl::compute_final_signature(&local_sigs, 3);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ use curv::cryptographic_primitives::secret_sharing::feldman_vss::VerifiableSS;
use curv::{BigInt, FE, GE};
use sha2::{Digest, Sha256};

pub mod mock_impl;
pub mod traits;

const SECURITY: usize = 256;

pub struct Keys {
Expand Down Expand Up @@ -348,3 +351,6 @@ mod tests {
assert_eq!(expected, compute_e(&v, &y, &message[..]));
}
}

#[cfg(test)]
mod test;
116 changes: 116 additions & 0 deletions src/crypto/multi_party_schnorr/traits.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use secp256k1::{constants, SecretKey};
use std::ops::Deref;

pub enum Error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why define these errors here, not in errors.rs?

VerifyVSS,
VerifyLocalSig,
}

pub type Message = [u8; 32];

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Secret([u8; 32]);

impl From<SecretKey> for Secret {
fn from(seckey: SecretKey) -> Self {
let mut data = [0u8; constants::SECRET_KEY_SIZE];
data.copy_from_slice(&seckey[..]);
Secret(data)
}
}

/// The schnorr signature what the distributed signing scheme produce finally
pub struct Signature {
/// R.x
pub r_x: [u8; 32],
/// sigma
pub sigma: [u8; 32],
}

pub mod key_generation_protocol {
use crate::crypto::multi_party_schnorr::traits::{Error, Secret};
use secp256k1::{PublicKey, SecretKey};
use std::collections::HashSet;

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct NodeVSS {
pub sender_pubkey: PublicKey,
pub receiver_pubkey: PublicKey,
pub commitments: Vec<PublicKey>,
pub secret: Secret,
}

/// Struct for a shared secret and an aggregated public key
#[derive(Clone, Debug)]
pub struct NodeShare {
/// Aggregated Public Key
pub aggregated_pubkey: PublicKey,
/// Secret share for a signer
pub secret_share: Secret,
}

pub trait KeyGenerationProtocol {
fn create_node_vss(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I prefer the return type of these functions is Result<...., Error> even if it does not return error now.

node_private_key: &SecretKey,
signer_keys: &Vec<PublicKey>,
threshold: usize,
) -> HashSet<NodeVSS>;
fn verify_node_vss(vss: &NodeVSS) -> Result<(), Error>;
fn aggregate_node_vss(vss_set: &HashSet<NodeVSS>) -> NodeShare;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should return Result<NodeShare, Error>

}
}

pub mod signature_issuing_protocol {
use crate::crypto::multi_party_schnorr::traits::key_generation_protocol::{NodeShare, NodeVSS};
use crate::crypto::multi_party_schnorr::traits::{Error, Message, Secret, Signature};
use secp256k1::{PublicKey, SecretKey};
use std::collections::HashSet;

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct BlockVSS {
pub sender_pubkey: PublicKey,
pub receiver_pubkey: PublicKey,
pub positive_commitments: Vec<PublicKey>,
pub positive_secret: Secret,
pub negative_commitments: Vec<PublicKey>,
pub negative_secret: Secret,
}

/// The Struct for a shared secret and an aggregated public key
#[derive(Clone, Debug)]
pub struct BlockShare {
/// Aggregated Public Key
pub aggregated_pubkey: PublicKey,
/// Secret share for a signer
pub positive_secret_share: Secret,
/// Secret share for a signer
pub negative_secret_share: Secret,
}

/// The Signature
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct LocalSig {
pub signer_pubkey: PublicKey,
pub gamma_i: Secret,
}

pub trait SignatureIssuingProtocol {
fn create_block_vss(signer_keys: &Vec<PublicKey>, threshold: usize) -> HashSet<BlockVSS>;
fn verify_block_vss(vss: &BlockVSS) -> Result<(), Error>;
fn aggregate_block_vss(vss_set: &HashSet<BlockVSS>) -> BlockShare;
fn create_local_sig(
message: &Message,
node_share: &NodeShare,
block_share: &BlockShare,
) -> LocalSig;
fn verify_local_sig(
local_sig: &LocalSig,
node_vss_set: &HashSet<NodeVSS>,
block_vss_set: &HashSet<BlockVSS>,
) -> Result<(), Error>;
fn compute_final_signature(
local_sigs: &HashSet<LocalSig>,
threshold: usize,
) -> Result<Signature, Error>;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have confidence whether the arguments are enough or not.
@Yamaguchi Can you check it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It need to have signer index to calculate Lagrange interpolation. I will add it into LocalSig.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To compute Signatre.r_x, a set of BlockVSS is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's true. I will add it.

}
}