libmilkyway 0.1.0

libmilkyway is a part of milkyway project providing common protocols for communicating between MilkyWay modules
Documentation
use libmilkyway_derive::{EnumDeserializable, EnumSerializable};
use crate::pki::hash::{CryptoHashable, HashType};
use crate::pki::impls::CryptoError;
use crate::pki::key::CryptoKey;
use crate::pki::signature::Signature;
use crate::serialization::deserializable::Deserializable;
use crate::serialization::error::SerializationError;
use crate::serialization::serializable::{Serializable, Serialized};

///
/// Ceritificate types
///
#[derive(PartialEq, Clone, Debug, EnumSerializable, EnumDeserializable)]
pub enum CertificateType{
    ///
    /// The certificate used only to sign other certificates
    ///
    RootCertificate,

    ///
    /// Certificate for signing data or other certificates
    ///
    SigningCertificate,

    ///
    /// Certificate with key that can be used for encipherment
    ///
    EnciphermentCertificate,
}


///
/// A PKI Certificate base trait
///
pub trait Certificate<PK: CryptoKey, SK: CryptoKey>: Serializable + Deserializable{
    ///
    /// Gets type of certificate
    ///
    fn get_type() -> CertificateType;

    ///
    /// Gets serial number of certificate
    ///
    fn get_serial(&self) -> u128;

    ///
    /// Get serial number of certificate with which this certificate is signed.
    /// Returns `None` if certificate is root.
    ///
    fn get_parent_serial(&self) -> Option<u128>;

    ///
    /// Get signature for certificate or gives `None` if certificate is root
    ///
    fn get_signature(&self) -> Option<Signature>;

    ///
    /// Gets certificate public key
    ///
    fn get_public_key(&self) -> PK;

    ///
    /// Gets certificate secret key if it is available
    ///
    fn get_secret_key(&self) -> Option<SK>;

    ///
    /// Clones certificate without private data
    ///
    fn clone_without_signature_and_sk(&self) -> Self;


    ///
    /// Clones certificate without signature(used for verifying signature)
    ///
    fn clone_without_signature(&self) -> Self;

    ///
    /// Signs piece of data with certificate secret key
    /// # Arguments
    ///
    /// * `data`: Data to sign
    /// * `hash_type`: Hash type to use during signature
    ///
    /// returns: Result<Signature, CryptoError>
    ///
    fn sign_data<T: Serializable + CryptoHashable>(&self, data: &T,
                                                   hash_type: HashType) -> Result<Signature, CryptoError>{
        let key_option = self.get_secret_key();
        if key_option.is_none(){
            return Err(CryptoError::ArgumentError("The certificate does not have private key"));
        }
        let m_type = Self::get_type();
        if m_type == CertificateType::EnciphermentCertificate{
            return Err(CryptoError::ArgumentError("Certificate is for encipherment, not signing"));
        }
        let key = key_option.unwrap();
        return key.sign(data, hash_type);
    }

    ///
    /// Verifies signature of data
    ///
    /// # Arguments
    ///
    /// * `data`: Data which signature must be verified
    /// * `signature`: Signature itself
    ///
    /// returns: bool
    ///
    fn verify_signature<T: Serializable + CryptoHashable>(&self, data: &T,
                                                          signature: &Signature) -> bool{
        let m_type = Self::get_type();
        if m_type == CertificateType::EnciphermentCertificate{
            panic!("Trying to use encipherment certificate for signature verification");
        }
        let key = self.get_public_key();
        key.verify_signature(data, signature)
    }

    ///
    /// Encrypts data with certificate public key
    /// # Arguments
    ///
    /// * `data`: Data to encrypt
    ///
    /// returns: Result<Vec<u8, Global>, CryptoError>
    ///
    fn encrypt<T: Serializable>(&self, data: &T) -> Result<Serialized, CryptoError>{
        let m_type = Self::get_type();
        if m_type != CertificateType::EnciphermentCertificate{
            return Err(CryptoError::ArgumentError("Using non-encipherment certificate for encryption"));
        }
        let key = self.get_public_key();
        key.encrypt(data)
    }

    ///
    /// Decrypts data with secret key of certificate
    /// # Arguments
    ///
    /// * `data`: Data to decrypt
    ///
    /// returns: Result<T, SerializationError>
    ///
    fn decrypt<T: Deserializable>(&self, data: &Serialized) -> Result<T, SerializationError>{
        let key_option = self.get_secret_key();
        //TODO: Use either CryptoError or proper SerializationError
        if key_option.is_none(){
            return Err(SerializationError::InvalidDataError(""));
        }
        let m_type = Self::get_type();
        if m_type != CertificateType::EnciphermentCertificate{
            return Err(SerializationError::InvalidDataError(""));
        }
        let key = key_option.unwrap();
        key.decrypt::<T>(data)
    }
    
    ///
    /// Gets name of certificate
    /// 
    /// returns: String: name of certificate
    ///
    fn get_name(&self) -> String;
}