use hmac::Mac;
use sha1::Sha1;
use sha2::{Sha256, Sha512};
pub trait AlgorithmTrait {
fn to_string(&self) -> String;
fn from_string(s: String) -> Option<Self>
where
Self: Sized;
fn hash(&self, secret: Vec<u8>, data: u64) -> Result<Vec<u8>, String>;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum Algorithm {
SHA1,
SHA256,
SHA512,
}
impl AlgorithmTrait for Algorithm {
fn to_string(&self) -> String {
match self {
Algorithm::SHA1 => "SHA1".into(),
Algorithm::SHA256 => "SHA256".into(),
Algorithm::SHA512 => "SHA512".into(),
}
}
fn from_string(name: String) -> Option<Self> {
match name.as_str() {
"SHA1" => Some(Algorithm::SHA1),
"SHA256" => Some(Algorithm::SHA256),
"SHA512" => Some(Algorithm::SHA512),
_ => None,
}
}
fn hash(&self, secret: Vec<u8>, data: u64) -> Result<Vec<u8>, String> {
match self {
Algorithm::SHA1 => match hmac::Hmac::<Sha1>::new_from_slice(secret.as_ref()) {
Ok(mut mac) => {
mac.update(&data.to_be_bytes());
Ok(mac.finalize().into_bytes().to_vec())
}
Err(e) => Err(e.to_string()),
},
Algorithm::SHA256 => match hmac::Hmac::<Sha256>::new_from_slice(secret.as_ref()) {
Ok(mut mac) => {
mac.update(&data.to_be_bytes());
Ok(mac.finalize().into_bytes().to_vec())
}
Err(e) => Err(e.to_string()),
},
Algorithm::SHA512 => match hmac::Hmac::<Sha512>::new_from_slice(secret.as_ref()) {
Ok(mut mac) => {
mac.update(&data.to_be_bytes());
Ok(mac.finalize().into_bytes().to_vec())
}
Err(e) => Err(e.to_string()),
},
}
}
}
#[cfg(test)]
mod algorithm_test;