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;
fn get_flags(&self) -> u128;
fn set_flags(&mut self, flags: u128);
#[inline]
fn check_flag(&self, mask: u128) -> bool{
self.get_flags() & mask != 0
}
fn set_flag(&mut self, mask: u128){
let current_flags = self.get_flags();
self.set_flags(current_flags | mask);
}
fn unset_flag(&mut self, mask: u128){
let current_flags = self.get_flags();
self.set_flags(current_flags & (!mask));
}
}
pub const FLAG_ROOT_CERT: u128 = 1;
pub const FLAG_USER_CERT: u128 = 1<<1;
pub const FLAG_SERVER_CERT: u128 = 1<<2;
pub const FLAG_CLIENT_CERT: u128 = 1<<3;
pub const FLAG_SIGN_CERTS: u128 = 1<<4;
pub const FLAG_SIGN_MESSAGES: u128 = 1<<5;
pub const FLAG_NO_WRITE: u128 = 1<<6;
pub const FLAG_NO_READ: u128 = 1<<7;