use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum HashAlgorithm {
Sha2256,
Sha2384,
Sha2512,
}
impl HashAlgorithm {
pub fn digest_size(&self) -> usize {
match self {
HashAlgorithm::Sha2256 => 32,
HashAlgorithm::Sha2384 => 48,
HashAlgorithm::Sha2512 => 64,
}
}
pub fn oid(&self) -> &'static str {
match self {
HashAlgorithm::Sha2256 => "2.16.840.1.101.3.4.2.1",
HashAlgorithm::Sha2384 => "2.16.840.1.101.3.4.2.2",
HashAlgorithm::Sha2512 => "2.16.840.1.101.3.4.2.3",
}
}
pub fn as_lowercase(&self) -> &'static str {
match self {
HashAlgorithm::Sha2256 => "sha256",
HashAlgorithm::Sha2384 => "sha384",
HashAlgorithm::Sha2512 => "sha512",
}
}
pub fn from_str_flexible(s: &str) -> Option<Self> {
match s.to_lowercase().as_str() {
"sha256" | "sha2_256" | "sha-256" => Some(HashAlgorithm::Sha2256),
"sha384" | "sha2_384" | "sha-384" => Some(HashAlgorithm::Sha2384),
"sha512" | "sha2_512" | "sha-512" => Some(HashAlgorithm::Sha2512),
_ => None,
}
}
}
impl std::fmt::Display for HashAlgorithm {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
HashAlgorithm::Sha2256 => write!(f, "SHA2_256"),
HashAlgorithm::Sha2384 => write!(f, "SHA2_384"),
HashAlgorithm::Sha2512 => write!(f, "SHA2_512"),
}
}
}
impl Serialize for HashAlgorithm {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
impl<'de> Deserialize<'de> for HashAlgorithm {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
HashAlgorithm::from_str_flexible(&s)
.ok_or_else(|| serde::de::Error::custom(format!("unknown hash algorithm: {}", s)))
}
}
pub use crate::encoding::base64_bytes;
pub mod hash_algorithm_lowercase {
use super::HashAlgorithm;
use serde::{Deserialize, Deserializer, Serializer};
pub fn serialize<S>(algo: &HashAlgorithm, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(algo.as_lowercase())
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<HashAlgorithm, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
HashAlgorithm::from_str_flexible(&s)
.ok_or_else(|| serde::de::Error::custom(format!("unknown hash algorithm: {}", s)))
}
}