use std::fmt;
use ed25519_dalek::{
Keypair,
SecretKey,
PublicKey,
Signature as Ed25519Signature,
Signer,
Verifier,
KEYPAIR_LENGTH,
SECRET_KEY_LENGTH,
};
use rand::rngs::OsRng;
use crate::{
Result,
ZffError,
ZffErrorKind,
ED25519_DALEK_SIGNATURE_LEN,
ED25519_DALEK_PUBKEY_LEN,
};
pub struct Signature;
impl Signature {
pub fn new_keypair() -> Keypair {
let mut csprng = OsRng{};
Keypair::generate(&mut csprng)
}
pub fn new_keypair_from_base64<K: Into<String>>(key: K) -> Result<Keypair> {
let key = base64::decode(&key.into())?;
if key.len() == KEYPAIR_LENGTH {
Ok(Keypair::from_bytes(&key)?)
} else if key.len() == SECRET_KEY_LENGTH {
let sec_key = SecretKey::from_bytes(&key)?;
let pub_key: PublicKey = (&sec_key).into();
let mut keypair_bytes = Vec::new();
keypair_bytes.append(&mut key.to_vec());
keypair_bytes.append(&mut pub_key.to_bytes().to_vec());
Ok(Keypair::from_bytes(&keypair_bytes)?)
} else {
Err(ZffError::new(ZffErrorKind::WrongSignatureKeyLength, ""))
}
}
pub fn sign(keypair: &Keypair, message: &[u8]) -> [u8; ED25519_DALEK_SIGNATURE_LEN] {
let signature = keypair.sign(message);
signature.to_bytes()
}
pub fn verify(publickey: [u8; ED25519_DALEK_PUBKEY_LEN], message: &[u8], signature: [u8; ED25519_DALEK_SIGNATURE_LEN]) -> Result<bool> {
let pub_key = PublicKey::from_bytes(&publickey)?;
let signature = Ed25519Signature::from_bytes(&signature)?;
match pub_key.verify(message, &signature) {
Ok(_) => Ok(true),
Err(_) => Ok(false),
}
}
pub fn calculate_signature(signature_keypair: Option<&Keypair>, buffer: &[u8]) -> Option<[u8; ED25519_DALEK_SIGNATURE_LEN]> {
signature_keypair.as_ref().map(|keypair| Signature::sign(keypair, buffer))
}
}
#[derive(Debug,Clone)]
pub enum SignatureFlag {
NoSignatures = 0,
HashValueSignatureOnly = 1,
PerChunkSignatures = 2,
}
impl fmt::Display for SignatureFlag {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let msg = match self {
SignatureFlag::NoSignatures => "NoSignatures",
SignatureFlag::HashValueSignatureOnly => "HashValueSignatureOnly",
SignatureFlag::PerChunkSignatures => "PerChunkSignatures",
};
write!(f, "{}", msg)
}
}