use crate::{Error, Result};
use crate::{PublicKey, SecretKey, Signature, SignatureShare};
use ed25519_dalek::Signer;
use rand::{CryptoRng, Rng};
use serde::{Deserialize, Serialize};
use std::fmt::{self, Debug, Formatter};
use std::sync::Arc;
use threshold_crypto::{self, serde_impl::SerdeSecret, PublicKeySet};
#[derive(Clone, PartialEq, Eq)]
pub enum OwnerType {
Single(PublicKey),
Multi(PublicKeySet),
}
impl OwnerType {
pub fn public_key(&self) -> PublicKey {
match self {
Self::Single(key) => *key,
Self::Multi(key_set) => PublicKey::Bls(key_set.public_key()),
}
}
pub fn public_key_set(&self) -> Result<PublicKeySet> {
match self {
Self::Single(_) => Err(Error::InvalidOwnerNotPublicKeySet),
Self::Multi(key_set) => Ok(key_set.clone()),
}
}
pub fn verify<T: Serialize>(&self, signature: &Signature, data: &T) -> bool {
let data = match bincode::serialize(&data) {
Err(_) => return false,
Ok(data) => data,
};
match signature {
Signature::Bls(sig) => {
if let OwnerType::Multi(set) = self {
set.public_key().verify(&sig, data)
} else {
false
}
}
ed @ Signature::Ed25519(_) => self.public_key().verify(ed, data).is_ok(),
Signature::BlsShare(share) => {
if let OwnerType::Multi(set) = self {
let pubkey_share = set.public_key_share(share.index);
pubkey_share.verify(&share.share, data)
} else {
false
}
}
}
}
}
impl Debug for OwnerType {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match self {
OwnerType::Single(_) => Debug::fmt(&self, f),
OwnerType::Multi(key_set) => write!(
f,
"OwnerType::Multi(PkSet {{ public_key: {:?} }})",
key_set.public_key()
),
}
}
}
pub trait Signing {
fn id(&self) -> OwnerType;
fn sign<T: Serialize>(&self, data: &T) -> Result<Signature>;
fn verify<T: Serialize>(&self, sig: &Signature, data: &T) -> bool;
}
impl Signing for Keypair {
fn id(&self) -> OwnerType {
match self {
Keypair::Ed25519(pair) => OwnerType::Single(PublicKey::Ed25519(pair.public)),
Keypair::BlsShare(share) => OwnerType::Multi(share.public_key_set.clone()),
}
}
fn sign<T: Serialize>(&self, data: &T) -> Result<Signature> {
let bytes = bincode::serialize(data).map_err(|e| Error::Serialisation(e.to_string()))?;
Ok(self.sign(&bytes))
}
fn verify<T: Serialize>(&self, signature: &Signature, data: &T) -> bool {
self.id().verify(signature, data)
}
}
#[derive(Serialize, Deserialize, Clone)]
pub enum Keypair {
Ed25519(Arc<ed25519_dalek::Keypair>),
BlsShare(Arc<BlsKeypairShare>),
}
impl Debug for Keypair {
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
write!(formatter, "Keypair::")?;
match self {
Self::Ed25519(_) => write!(formatter, "Ed25519(..)"),
Self::BlsShare(_) => write!(formatter, "BlsShare(..)"),
}
}
}
impl PartialEq for Keypair {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Ed25519(keypair), Self::Ed25519(other_keypair)) => {
keypair.to_bytes().to_vec() == other_keypair.to_bytes().to_vec()
}
(Self::BlsShare(keypair), Self::BlsShare(other_keypair)) => keypair == other_keypair,
_ => false,
}
}
}
impl Eq for Keypair {}
impl Keypair {
pub fn new_ed25519<T: CryptoRng + Rng>(rng: &mut T) -> Self {
let keypair = ed25519_dalek::Keypair::generate(rng);
Self::Ed25519(Arc::new(keypair))
}
pub fn new_bls_share(
index: usize,
secret_share: threshold_crypto::SecretKeyShare,
public_key_set: PublicKeySet,
) -> Self {
Self::BlsShare(Arc::new(BlsKeypairShare {
index,
secret: SerdeSecret(secret_share.clone()),
public: secret_share.public_key_share(),
public_key_set,
}))
}
pub fn public_key(&self) -> PublicKey {
match self {
Self::Ed25519(keypair) => PublicKey::Ed25519(keypair.public),
Self::BlsShare(keypair) => PublicKey::BlsShare(keypair.public),
}
}
pub fn secret_key(&self) -> Result<SecretKey> {
match self {
Self::Ed25519(keypair) => {
let bytes = keypair.secret.to_bytes();
match ed25519_dalek::SecretKey::from_bytes(&bytes) {
Ok(sk) => Ok(SecretKey::Ed25519(sk)),
Err(_) => Err(Error::FailedToParse(
"Could not deserialise Ed25519 secret key".to_string(),
)),
}
}
Self::BlsShare(keypair) => Ok(SecretKey::BlsShare(keypair.secret.clone())),
}
}
pub fn sign(&self, data: &[u8]) -> Signature {
match self {
Self::Ed25519(keypair) => Signature::Ed25519(keypair.sign(&data)),
Self::BlsShare(keypair) => Signature::BlsShare(SignatureShare {
index: keypair.index,
share: keypair.secret.sign(data),
}),
}
}
}
impl From<ed25519_dalek::SecretKey> for Keypair {
fn from(secret: ed25519_dalek::SecretKey) -> Self {
let keypair = ed25519_dalek::Keypair {
public: (&secret).into(),
secret,
};
Self::Ed25519(Arc::new(keypair))
}
}
#[derive(Clone, PartialEq, Serialize, Deserialize)]
pub struct BlsKeypairShare {
pub index: usize,
pub secret: SerdeSecret<threshold_crypto::SecretKeyShare>,
pub public: threshold_crypto::PublicKeyShare,
pub public_key_set: PublicKeySet,
}
impl Debug for BlsKeypairShare {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(
f,
"BlsKeyPairShare {{ index: {:?}, secret: {:?}, public: {:?}, public_key_set: PkSet {{ public_key: {:?} }} }}",
self.index,
self.secret,
self.public,
self.public_key_set.public_key()
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::utils;
fn gen_keypairs() -> Vec<Keypair> {
let mut rng = rand::thread_rng();
let bls_secret_key = threshold_crypto::SecretKeySet::random(1, &mut rng);
vec![
Keypair::new_ed25519(&mut rng),
Keypair::new_bls_share(
0,
bls_secret_key.secret_key_share(0),
bls_secret_key.public_keys(),
),
]
}
#[test]
fn serialisation_key_pair() -> Result<()> {
let keypairs = gen_keypairs();
for keypair in keypairs {
let encoded = utils::serialise(&keypair)?;
let decoded: Keypair = utils::deserialise(&encoded)?;
assert_eq!(decoded, keypair);
}
Ok(())
}
}