use ed25519_dalek::{Keypair as Ed25519Keypair, PublicKey, SecretKey, Signature, Signer, Verifier};
use rand::rngs::OsRng;
use serde::{Deserialize, Serialize};
use crate::identity::KeyPairError;
#[derive(Debug, Serialize, Deserialize)]
pub struct KeyPair(Ed25519Keypair);
impl KeyPair {
pub fn new() -> Self {
let mut csprng: OsRng = OsRng {};
let key_pair = Ed25519Keypair::generate(&mut csprng);
Self(key_pair)
}
pub fn from_private_key(private_key: &SecretKey) -> Result<Self, KeyPairError> {
let public_key: PublicKey = private_key.into();
let bytes = [private_key.to_bytes(), public_key.to_bytes()].concat();
let key_pair = Ed25519Keypair::from_bytes(&bytes)?;
Ok(KeyPair(key_pair))
}
pub fn from_private_key_str(private_key: &str) -> Result<Self, KeyPairError> {
let secret_key_bytes = hex::decode(private_key)?;
let secret_key = SecretKey::from_bytes(&secret_key_bytes)?;
Self::from_private_key(&secret_key)
}
pub fn public_key(&self) -> &PublicKey {
&self.0.public
}
pub fn private_key(&self) -> &SecretKey {
&self.0.secret
}
pub fn sign(&self, bytes: &[u8]) -> Signature {
self.0.sign(bytes)
}
pub fn verify(
public_key: &PublicKey,
bytes: &[u8],
signature: &Signature,
) -> Result<(), KeyPairError> {
public_key.verify(bytes, signature)?;
Ok(())
}
}
impl Default for KeyPair {
fn default() -> Self {
KeyPair::new()
}
}
#[cfg(test)]
mod tests {
use ed25519_dalek::{PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH};
use super::KeyPair;
#[test]
fn makes_keypair() {
let key_pair = KeyPair::new();
assert_eq!(key_pair.public_key().to_bytes().len(), PUBLIC_KEY_LENGTH);
assert_eq!(key_pair.private_key().to_bytes().len(), SECRET_KEY_LENGTH);
}
#[test]
fn key_pair_from_private_key() {
let key_pair = KeyPair::new();
let key_pair2 = KeyPair::from_private_key(key_pair.private_key()).unwrap();
assert_eq!(key_pair.public_key(), key_pair2.public_key());
}
#[test]
fn signing() {
let key_pair = KeyPair::new();
let bytes = b"test";
let signature = key_pair.sign(bytes);
assert!(KeyPair::verify(key_pair.public_key(), bytes, &signature).is_ok());
assert!(KeyPair::verify(key_pair.public_key(), b"not test", &signature).is_err());
let key_pair_2 = KeyPair::new();
assert!(KeyPair::verify(key_pair_2.public_key(), bytes, &signature).is_err());
}
}