pub(crate) mod ed25519;
pub(crate) mod error;
#[cfg(feature = "secp256k1")]
pub(crate) mod secp256k1;
use std::io::Read;
use borsh::{BorshDeserialize, BorshSerialize};
use identifier::error::Error;
use base64::encode_config;
pub use ed25519::Ed25519KeyPair;
#[cfg(feature = "secp256k1")]
pub use secp256k1::Secp256k1KeyPair;
use serde::{Deserialize, Serialize};
use crate::identifier::{self, derive::KeyDerivator};
#[derive(Serialize, Deserialize, Debug)]
pub enum KeyPair {
Ed25519(Ed25519KeyPair),
#[cfg(feature = "secp256k1")]
Secp256k1(Secp256k1KeyPair),
}
impl KeyPair {
pub fn get_key_derivator(&self) -> KeyDerivator {
match self {
KeyPair::Ed25519(_) => KeyDerivator::Ed25519,
KeyPair::Secp256k1(_) => KeyDerivator::Secp256k1,
}
}
}
#[allow(dead_code)]
pub fn generate<T: KeyGenerator + DSA + Into<KeyPair>>(seed: Option<&[u8]>) -> KeyPair {
T::from_seed(seed.map_or(vec![].as_slice(), |x| x)).into()
}
#[derive(Default, Debug, Clone, PartialEq)]
pub struct BaseKeyPair<P, K> {
pub public_key: P,
pub secret_key: Option<K>,
}
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CryptoBox {
pub public_key: Vec<u8>,
pub secret_key: Vec<u8>,
}
pub trait KeyMaterial {
fn public_key_bytes(&self) -> Vec<u8>;
fn secret_key_bytes(&self) -> Vec<u8>;
fn to_bytes(&self) -> Vec<u8>;
fn to_str(&self) -> String {
encode_config(self.to_bytes(), base64::URL_SAFE_NO_PAD)
}
}
pub trait KeyGenerator: KeyMaterial {
fn new() -> Self
where
Self: Sized,
{
Self::from_seed(vec![].as_slice())
}
fn from_seed(seed: &[u8]) -> Self
where
Self: Sized;
fn from_public_key(public_key: &[u8]) -> Self
where
Self: Sized;
fn from_secret_key(private_key: &[u8]) -> Self
where
Self: Sized;
}
pub trait DSA {
fn sign(&self, payload: Payload) -> Result<Vec<u8>, Error>;
fn verify(&self, payload: Payload, signature: &[u8]) -> Result<(), Error>;
}
pub trait DHKE {
fn key_exchange(&self, their_public: &Self) -> Result<Vec<u8>, Error>;
}
impl Clone for KeyPair {
fn clone(&self) -> Self {
match self {
KeyPair::Ed25519(kp) => {
KeyPair::Ed25519(Ed25519KeyPair::from_secret_key(&kp.secret_key_bytes()))
}
KeyPair::Secp256k1(kp) => {
KeyPair::Secp256k1(Secp256k1KeyPair::from_secret_key(&kp.secret_key_bytes()))
}
}
}
}
impl KeyMaterial for KeyPair {
fn public_key_bytes(&self) -> Vec<u8> {
match self {
KeyPair::Ed25519(x) => x.public_key_bytes(),
#[cfg(feature = "secp256k1")]
KeyPair::Secp256k1(x) => x.public_key_bytes(),
}
}
fn secret_key_bytes(&self) -> Vec<u8> {
match self {
KeyPair::Ed25519(x) => x.secret_key_bytes(),
#[cfg(feature = "secp256k1")]
KeyPair::Secp256k1(x) => x.secret_key_bytes(),
}
}
fn to_bytes(&self) -> Vec<u8> {
match self {
KeyPair::Ed25519(x) => x.to_bytes(),
#[cfg(feature = "secp256k1")]
KeyPair::Secp256k1(x) => x.to_bytes(),
}
}
}
impl DSA for KeyPair {
fn sign(&self, payload: Payload) -> Result<Vec<u8>, Error> {
match self {
KeyPair::Ed25519(x) => x.sign(payload),
#[cfg(feature = "secp256k1")]
KeyPair::Secp256k1(x) => x.sign(payload),
}
}
fn verify(&self, payload: Payload, signature: &[u8]) -> Result<(), Error> {
match self {
KeyPair::Ed25519(x) => x.verify(payload, signature),
#[cfg(feature = "secp256k1")]
KeyPair::Secp256k1(x) => x.verify(payload, signature),
}
}
}
impl BorshSerialize for KeyPair {
#[inline]
fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
match &self {
KeyPair::Ed25519(x) => {
BorshSerialize::serialize(&0u8, writer)?;
let a: [u8; 32] = x.secret_key_bytes().try_into().unwrap();
BorshSerialize::serialize(&a, writer)
}
KeyPair::Secp256k1(x) => {
BorshSerialize::serialize(&1u8, writer)?;
let a: [u8; 32] = x.secret_key_bytes().try_into().unwrap();
BorshSerialize::serialize(&a, writer)
}
}
}
}
impl BorshDeserialize for KeyPair {
#[inline]
fn deserialize_reader<R: Read>(reader: &mut R) -> std::io::Result<Self> {
let order: u8 = BorshDeserialize::deserialize_reader(reader)?;
match order {
0 => {
let data: [u8; 32] = BorshDeserialize::deserialize_reader(reader)?;
Ok(KeyPair::Ed25519(Ed25519KeyPair::from_secret_key(&data)))
}
1 => {
let data: [u8; 32] = BorshDeserialize::deserialize_reader(reader)?;
Ok(KeyPair::Secp256k1(Secp256k1KeyPair::from_secret_key(&data)))
}
_ => Err(std::io::Error::new(
std::io::ErrorKind::InvalidInput,
format!("Invalid Value representation: {}", order),
)),
}
}
}
#[derive(Debug, Clone)]
pub enum Payload {
Buffer(Vec<u8>),
#[allow(dead_code)]
BufferArray(Vec<Vec<u8>>),
}
pub fn create_seed(initial_seed: &[u8]) -> Result<[u8; 32], Error> {
let mut seed = [0u8; 32];
if initial_seed.is_empty() {
getrandom::getrandom(&mut seed)
.map_err(|_| Error::SeedError("couldn't generate random seed".to_owned()))?;
} else if initial_seed.len() <= 32 {
seed[..initial_seed.len()].copy_from_slice(initial_seed);
} else {
return Err(Error::SeedError("seed is greater than 32".to_owned()));
}
Ok(seed)
}
#[cfg(test)]
mod tests {
use super::{create_seed, ed25519::Ed25519KeyPair, generate, Payload, DSA};
#[cfg(feature = "secp256k1")]
use super::secp256k1::Secp256k1KeyPair;
#[test]
fn test_create_seed() {
assert!(create_seed(vec![].as_slice()).is_ok());
let seed = "48s8j34fuadfeuijakqp93d56829ki21".as_bytes();
assert!(create_seed(seed).is_ok());
let seed = "witness".as_bytes();
assert!(create_seed(seed).is_ok());
let seed = "witnesssdfasfasfasfsafsafasfsafsa".as_bytes();
assert!(create_seed(seed).is_err());
}
#[test]
fn test_ed25519() {
let key_pair = generate::<Ed25519KeyPair>(None);
let message = b"secret message";
let signature = key_pair.sign(Payload::Buffer(message.to_vec())).unwrap();
println!("Tamaño: {}", signature.len());
let valid = key_pair.verify(Payload::Buffer(message.to_vec()), &signature);
matches!(valid, Ok(()));
}
#[test]
#[cfg(feature = "secp256k1")]
fn test_secp256k1() {
let key_pair = generate::<Secp256k1KeyPair>(None);
let message = b"secret message";
let signature = key_pair.sign(Payload::Buffer(message.to_vec())).unwrap();
println!("Tamaño: {}", signature.len());
let valid = key_pair.verify(Payload::Buffer(message.to_vec()), &signature);
matches!(valid, Ok(()));
}
}