use crate::cryptography::hmac_sign::{Sign, SignType, Operation, SignatureData};
use hmac::{Hmac, Mac};
use sha2::{Sha512, Sha256};
impl Sign {
pub fn new(data: Vec<u8>, passphrase: Vec<u8>, status: Operation, hash_type: SignType) -> Self {
let data = SignatureData {
data, passphrase, hmac: Vec::new(), concat_data: Vec::new()
};
match hash_type {
SignType::Sha512 => Sign { data, status, hash_type, length: 64, veryfied: false},
SignType::Sha256 => Sign { data, status, hash_type, length: 32, veryfied: false},
_ => Sign { data, status, hash_type, length: 64, veryfied: false},
}
}
pub fn hmac(&mut self) -> Vec<u8> {
match &self.status {
Operation::Sign => self.generate_hmac(),
Operation::Verify => self.verify_hmac().unwrap(),
}
}
pub fn generate_hmac(&self) -> Vec<u8> {
let data = &self.data.data;
match &self.hash_type {
SignType::Sha512 => {
let mut mac = <Hmac<Sha512> as Mac>::new_from_slice(&self.data.passphrase)
.expect("HMAC can take key of any size");
mac.update(data);
let hmac = mac.finalize().into_bytes().to_vec();
let concat_data = [&self.data.data, hmac.as_slice()].concat();
concat_data
},
SignType::Sha256 => {
let mut mac = <Hmac<Sha256> as Mac>::new_from_slice(&self.data.passphrase)
.expect("HMAC can take key of any size");
mac.update(data);
let hmac = mac.finalize().into_bytes().to_vec();
let concat_data = [&self.data.data, hmac.as_slice()].concat();
concat_data
},
_ => vec![],
}
}
fn verify_hmac_sha512(data: &[u8], hmac: &[u8], passphrase: &[u8]) -> bool {
let mut mac = <Hmac<Sha512> as Mac>::new_from_slice(passphrase)
.expect("HMAC can take key of any size");
mac.update(data);
mac.verify_slice(hmac).is_ok()
}
fn verify_hmac_sha256(data: &[u8], hmac: &[u8], passphrase: &[u8]) -> bool {
let mut mac = <Hmac<Sha256> as Mac>::new_from_slice(passphrase)
.expect("HMAC can take key of any size");
mac.update(data);
mac.verify_slice(hmac).is_ok()
}
pub fn verify_hmac(&self) -> Result<Vec<u8>, &'static str> {
if self.data.data.len() < self.length {
return Err("Data is too short for HMAC verification");
}
let (data, hmac) = self.data.data.split_at(self.data.data.len() - self.length);
let verification_success = match &self.hash_type {
SignType::Sha512 => Self::verify_hmac_sha512(data, hmac, &self.data.passphrase),
SignType::Sha256 => Self::verify_hmac_sha256(data, hmac, &self.data.passphrase),
_ => return Err("Unsupported HMAC hash type"),
};
if verification_success {
Ok(data.to_owned())
} else {
Err("HMAC verification failed")
}
}
}