use std::fmt;
use super::keys::{PublicKey, PublicKeyFormat};
use super::signature::{SignatureAlgorithm, Signature};
pub trait Signer {
type KeyId;
type Error: fmt::Debug + fmt::Display;
fn create_key(
&self,
algorithm: PublicKeyFormat
) -> Result<Self::KeyId, Self::Error>;
fn get_key_info(
&self,
key: &Self::KeyId
) -> Result<PublicKey, KeyError<Self::Error>>;
fn destroy_key(
&self,
key: &Self::KeyId
) -> Result<(), KeyError<Self::Error>>;
fn sign<Alg: SignatureAlgorithm, D: AsRef<[u8]> + ?Sized>(
&self,
key: &Self::KeyId,
algorithm: Alg,
data: &D
) -> Result<Signature<Alg>, SigningError<Self::Error>>;
fn sign_one_off<Alg: SignatureAlgorithm, D: AsRef<[u8]> + ?Sized>(
&self,
algorithm: Alg,
data: &D
) -> Result<(Signature<Alg>, PublicKey), Self::Error>;
fn rand(&self, target: &mut [u8]) -> Result<(), Self::Error>;
}
#[derive(Clone, Copy, Debug)]
pub enum SigningAlgorithm {
RsaSha256,
EcdsaP256Sha256,
}
impl SigningAlgorithm {
pub fn public_key_format(self) -> PublicKeyFormat {
match self {
SigningAlgorithm::RsaSha256 => PublicKeyFormat::Rsa,
SigningAlgorithm::EcdsaP256Sha256 => PublicKeyFormat::EcdsaP256,
}
}
}
#[derive(Clone, Debug)]
pub enum KeyError<S> {
KeyNotFound,
Signer(S)
}
impl<S> From<S> for KeyError<S> {
fn from(err: S) -> Self {
KeyError::Signer(err)
}
}
impl<S: fmt::Display> fmt::Display for KeyError<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::KeyError::*;
match *self {
KeyNotFound => write!(f, "key not found"),
Signer(ref s) => s.fmt(f)
}
}
}
#[derive(Clone, Debug)]
pub enum SigningError<S> {
KeyNotFound,
IncompatibleKey,
Signer(S)
}
impl<S> From<S> for SigningError<S> {
fn from(err: S) -> Self {
SigningError::Signer(err)
}
}
impl<S> From<KeyError<S>> for SigningError<S> {
fn from(err: KeyError<S>) -> Self {
match err {
KeyError::KeyNotFound => SigningError::KeyNotFound,
KeyError::Signer(err) => SigningError::Signer(err)
}
}
}
impl<S: fmt::Display> fmt::Display for SigningError<S> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use self::SigningError::*;
match *self {
KeyNotFound => write!(f, "key not found"),
IncompatibleKey => write!(f, "key not compatible with algorithm"),
Signer(ref s) => s.fmt(f)
}
}
}