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};
#[derive(PartialEq, Clone, Debug, EnumSerializable, EnumDeserializable)]
pub enum CertificateType{
RootCertificate,
SigningCertificate,
EnciphermentCertificate,
}
pub trait Certificate<PK: CryptoKey, SK: CryptoKey>: Serializable + Deserializable{
fn get_type() -> CertificateType;
fn get_serial(&self) -> u128;
fn get_parent_serial(&self) -> Option<u128>;
fn get_signature(&self) -> Option<Signature>;
fn get_public_key(&self) -> PK;
fn get_secret_key(&self) -> Option<SK>;
fn clone_without_signature_and_sk(&self) -> Self;
fn clone_without_signature(&self) -> Self;
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);
}
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)
}
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)
}
fn decrypt<T: Deserializable>(&self, data: &Serialized) -> Result<T, SerializationError>{
let key_option = self.get_secret_key();
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)
}
fn get_name(&self) -> String;
}