use crate::bls::{Signature, VerificationResult};
use crate::traits::{PRSKey, ThresholdKey};
use crate::utils::{lambda_coeff, poly_eval};
use bls12_381::{G1Affine, G2Affine, Scalar};
use getrandom;
use sha2::{Digest, Sha512};
pub(crate) const SCALAR_BYTES_LENGTH: usize = 32;
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub struct PublicKey(pub(crate) G1Affine);
#[derive(Debug, Eq, PartialEq, Clone, Copy)]
pub struct PrivateKey(pub(crate) Scalar, pub(crate) Option<Scalar>);
impl PrivateKey {
pub fn random() -> PrivateKey {
let mut key_bytes = [0u8; 64];
match getrandom::getrandom(&mut key_bytes) {
Ok(_) => return PrivateKey(Scalar::from_bytes_wide(&key_bytes), None),
Err(err) => panic!("Error while generating a random key: {:?}", err),
};
}
pub fn public_key(&self) -> PublicKey {
PublicKey((&G1Affine::generator() * &self.0).into())
}
pub fn sign(&self, message_element: &G2Affine) -> Signature {
Signature::new(self, message_element)
}
pub fn to_bytes(&self, buff: &mut [u8]) {
buff[0..32].copy_from_slice(&self.0.to_bytes()[..]);
if let Some(fragment_index) = self.1 {
buff[32..64].copy_from_slice(&fragment_index.to_bytes()[..]);
}
}
pub fn from_bytes(bytes: &[u8]) -> PrivateKey {
let mut scalar_bytes = [0u8; 32];
let fragment_index: Option<Scalar>;
if bytes.len() == SCALAR_BYTES_LENGTH {
scalar_bytes.copy_from_slice(&bytes);
fragment_index = None;
} else {
let mut index_bytes = [0u8; 32];
scalar_bytes.copy_from_slice(&bytes[0..SCALAR_BYTES_LENGTH]);
index_bytes.copy_from_slice(&bytes[SCALAR_BYTES_LENGTH..64]);
fragment_index = Some(Scalar::from_bytes(&index_bytes).unwrap());
}
PrivateKey(Scalar::from_bytes(&scalar_bytes).unwrap(), fragment_index)
}
}
impl PublicKey {
pub fn verify(&self, message_element: &G2Affine, signature: &Signature) -> VerificationResult {
signature.verify(self, message_element)
}
pub fn to_bytes(&self) -> [u8; 48] {
self.0.to_compressed()
}
pub fn from_bytes(bytes: &[u8; 48]) -> PublicKey {
PublicKey(G1Affine::from_compressed(bytes).unwrap())
}
}
impl From<PrivateKey> for PublicKey {
fn from(priv_key: PrivateKey) -> Self {
priv_key.public_key()
}
}
impl ThresholdKey for PrivateKey {
fn split(&self, m: usize, n: usize) -> Vec<PrivateKey> {
let mut coeffs = Vec::<Scalar>::with_capacity(m);
coeffs.push(self.0);
for _ in 1..m {
coeffs.push(PrivateKey::random().0);
}
let mut fragments = Vec::<PrivateKey>::with_capacity(n);
for _ in 0..n {
let fragment_index = PrivateKey::random().0;
fragments.push(PrivateKey(
poly_eval(&coeffs[..], &fragment_index),
Some(fragment_index),
));
}
fragments
}
fn recover(fragments: &[PrivateKey]) -> PrivateKey {
let mut fragment_indices = [Scalar::zero(); 256];
for i in 0..fragments.len() {
fragment_indices[i] = fragments[i].1.unwrap();
}
let mut result = Scalar::zero();
for fragment in fragments.iter() {
result += lambda_coeff(&fragment.1.unwrap(), &fragment_indices[..fragments.len()])
* fragment.0;
}
PrivateKey(result, None)
}
fn is_fragment(&self) -> bool {
match self.1 {
Some(_) => true,
None => false,
}
}
}
impl PRSKey for PrivateKey {
fn resigning_key(&self, bob_pubkey: &PublicKey) -> PrivateKey {
let phi_b = self.designated_key(&bob_pubkey).0;
PrivateKey(self.0 * (phi_b.invert().unwrap()), None)
}
fn designated_key(&self, alice_pubkey: &PublicKey) -> PrivateKey {
let dh = Sha512::digest(&G1Affine::from(alice_pubkey.0 * &self.0).to_uncompressed());
let mut scalar_bytes = [0u8; 64];
scalar_bytes.copy_from_slice(&dh.as_slice());
PrivateKey(Scalar::from_bytes_wide(&scalar_bytes), None)
}
fn resign(&self, signature: &Signature) -> Signature {
Signature::new(&self, &signature.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::traits::ThresholdSignature;
#[test]
fn test_random() {
let a = PrivateKey::random();
let b = PrivateKey::random();
assert_ne!(a, b);
}
#[test]
fn test_pubkey() {
let priv_a = PrivateKey::random();
let pub_a = priv_a.public_key();
assert_eq!(PublicKey::from(priv_a), pub_a);
}
#[test]
fn test_signing_and_verifying() {
let priv_a = PrivateKey::random();
let pub_a = priv_a.public_key();
let rand = PrivateKey::random();
let msg = G2Affine::from(G2Affine::generator() * &rand.0);
let sig_msg = priv_a.sign(&msg);
assert_eq!(sig_msg, Signature::new(&priv_a, &msg));
let verified = pub_a.verify(&msg, &sig_msg);
assert_eq!(verified, sig_msg.verify(&pub_a, &msg));
assert_eq!(verified, VerificationResult::Valid);
let new_rand = PrivateKey::random();
let bad_msg = G2Affine::from(G2Affine::generator() * &new_rand.0);
assert_ne!(bad_msg, msg);
let not_verified = pub_a.verify(&bad_msg, &sig_msg);
assert_eq!(not_verified, VerificationResult::Invalid);
}
#[test]
fn test_verification_result_handling() {
let priv_a = PrivateKey::random();
let pub_a = priv_a.public_key();
let rand = PrivateKey::random();
let msg = G2Affine::from(G2Affine::generator() * &rand.0);
let sig_msg = priv_a.sign(&msg);
fn handle_signature_verification(is_verified: &VerificationResult) -> &str {
match is_verified {
VerificationResult::Valid => "Valid message!",
VerificationResult::Invalid => "Invalid message!",
}
}
let verified = pub_a.verify(&msg, &sig_msg);
assert_eq!("Valid message!", handle_signature_verification(&verified));
let new_rand = PrivateKey::random();
let bad_msg = G2Affine::from(G2Affine::generator() * &new_rand.0);
let not_verified = pub_a.verify(&bad_msg, &sig_msg);
assert_eq!(
"Invalid message!",
handle_signature_verification(¬_verified)
);
}
#[test]
fn test_key_split_3_of_5() {
let priv_a = PrivateKey::random();
let n_frags = priv_a.split(3, 5);
let m_frags = &n_frags[0..3];
let recovered_a = PrivateKey::recover(&m_frags);
assert_eq!(recovered_a, priv_a);
}
#[test]
fn test_key_serialization() {
let priv_a = PrivateKey::random();
let n_frags = priv_a.split(3, 5);
let mut a_bytes = [0u8; 32];
let mut frag_bytes = [0u8; 64];
priv_a.to_bytes(&mut a_bytes);
n_frags[0].to_bytes(&mut frag_bytes);
assert_eq!(a_bytes.len(), 32);
assert_eq!(frag_bytes.len(), 64);
assert_ne!(a_bytes[..32], frag_bytes[..32]);
assert_eq!(PrivateKey::from_bytes(&a_bytes), priv_a);
assert_eq!(PrivateKey::from_bytes(&frag_bytes), n_frags[0]);
}
#[test]
fn test_signature_serialization() {
let priv_a = PrivateKey::random();
let n_frags = priv_a.split(3, 5);
let rand = PrivateKey::random();
let msg = G2Affine::from(G2Affine::generator() * &rand.0);
let sig = priv_a.sign(&msg);
let frag_sig = n_frags[0].sign(&msg);
let mut sig_bytes = [0u8; 96];
let mut frag_sig_bytes = [0u8; 128];
sig.to_bytes(&mut sig_bytes);
frag_sig.to_bytes(&mut frag_sig_bytes);
assert_eq!(sig_bytes.len(), 96);
assert_eq!(frag_sig_bytes.len(), 128);
assert_ne!(sig_bytes[..96], frag_sig_bytes[..96]);
assert_eq!(Signature::from_bytes(&sig_bytes), sig);
assert_eq!(Signature::from_bytes(&frag_sig_bytes), frag_sig);
}
#[test]
fn test_is_fragment() {
let priv_a = PrivateKey::random();
let n_frags = priv_a.split(3, 5);
assert_eq!(n_frags[0].is_fragment(), true);
assert_eq!(priv_a.is_fragment(), false);
let rand = PrivateKey::random();
let msg = G2Affine::from(G2Affine::generator() * &rand.0);
let sig = n_frags[0].sign(&msg);
assert_eq!(sig.is_fragment(), true);
assert_eq!(priv_a.sign(&msg).is_fragment(), false);
}
#[test]
fn test_incomplete_key_recovery() {
let priv_a = PrivateKey::random();
let n_frags = priv_a.split(3, 5);
let m_frags = &n_frags[0..2];
let bad_recovery = PrivateKey::recover(&m_frags);
assert_ne!(bad_recovery, priv_a);
}
#[test]
fn test_threshold_signature_3_of_5() {
let priv_a = PrivateKey::random();
let n_frags = priv_a.split(3, 5);
let rand = PrivateKey::random();
let msg = G2Affine::from(G2Affine::generator() * &rand.0);
let sig_1 = n_frags[0].sign(&msg);
let sig_2 = n_frags[1].sign(&msg);
let sig_3 = n_frags[3].sign(&msg);
let sig_frags = vec![sig_1, sig_2, sig_3];
let full_sig = Signature::assemble(&sig_frags[..]);
let msg_sig = priv_a.sign(&msg);
assert_eq!(msg_sig, full_sig);
let pub_a = priv_a.public_key();
assert_eq!(pub_a.verify(&msg, &full_sig), VerificationResult::Valid);
}
#[test]
fn test_unordered_index_key_recovery() {
let priv_a = PrivateKey::random();
let n_frags = priv_a.split(3, 5);
let m_frags = &n_frags[2..5];
let recovered_a = PrivateKey::recover(&m_frags);
assert_eq!(recovered_a, priv_a);
}
#[test]
fn test_unordered_index_signature_assembly() {
let priv_a = PrivateKey::random();
let n_frags = priv_a.split(3, 5);
let rand = PrivateKey::random();
let msg = G2Affine::from(G2Affine::generator() * &rand.0);
let sig_1 = n_frags[0].sign(&msg);
let sig_2 = n_frags[1].sign(&msg);
let sig_3 = n_frags[3].sign(&msg);
let sig_frags = vec![sig_1, sig_2, sig_3];
let full_sig = Signature::assemble(&sig_frags[..]);
let pub_a = priv_a.public_key();
assert_eq!(pub_a.verify(&msg, &full_sig), VerificationResult::Valid);
}
#[test]
fn test_incomplete_signature_assembly() {
let priv_a = PrivateKey::random();
let n_frags = priv_a.split(3, 5);
let rand = PrivateKey::random();
let msg = G2Affine::from(G2Affine::generator() * &rand.0);
let sig_1 = n_frags[0].sign(&msg);
let sig_2 = n_frags[1].sign(&msg);
let sig_frags = vec![sig_1, sig_2];
let bad_sig = Signature::assemble(&sig_frags[..]);
let msg_sig = priv_a.sign(&msg);
assert_ne!(msg_sig, bad_sig);
}
#[test]
fn test_proxy_re_signature() {
let priv_alice = PrivateKey::random();
let pub_alice = priv_alice.public_key();
let priv_bob = PrivateKey::random();
let pub_bob = priv_bob.public_key();
let rand = PrivateKey::random();
let msg = G2Affine::from(G2Affine::generator() * &rand.0);
let rekey_ab = priv_alice.resigning_key(&pub_bob);
let sig_b = priv_bob.designated_key(&pub_alice).sign(&msg);
assert_ne!(sig_b, priv_bob.sign(&msg));
assert_eq!(pub_bob.verify(&msg, &sig_b), VerificationResult::Invalid);
let sig_a = rekey_ab.resign(&sig_b);
assert_eq!(sig_a, priv_alice.sign(&msg));
assert_eq!(pub_alice.verify(&msg, &sig_a), VerificationResult::Valid);
}
}