use jsonwebtoken::{Algorithm, DecodingKey};
use zeroize::Zeroizing;
use crate::security::errors::SecurityError;
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum SigningKey {
Hs256(Zeroizing<Vec<u8>>),
Hs384(Zeroizing<Vec<u8>>),
Hs512(Zeroizing<Vec<u8>>),
Rs256Pem(String),
Rs384Pem(String),
Rs512Pem(String),
Rs256Components {
n: String,
e: String,
},
}
impl SigningKey {
#[must_use]
pub fn hs256(secret: &str) -> Self {
Self::Hs256(Zeroizing::new(secret.as_bytes().to_vec()))
}
#[must_use]
pub fn hs256_bytes(secret: &[u8]) -> Self {
Self::Hs256(Zeroizing::new(secret.to_vec()))
}
#[must_use]
pub fn rs256_pem(pem: &str) -> Self {
Self::Rs256Pem(pem.to_string())
}
#[must_use]
pub fn rs256_components(n: &str, e: &str) -> Self {
Self::Rs256Components {
n: n.to_string(),
e: e.to_string(),
}
}
#[must_use]
pub const fn algorithm(&self) -> Algorithm {
match self {
Self::Hs256(_) => Algorithm::HS256,
Self::Hs384(_) => Algorithm::HS384,
Self::Hs512(_) => Algorithm::HS512,
Self::Rs256Pem(_) | Self::Rs256Components { .. } => Algorithm::RS256,
Self::Rs384Pem(_) => Algorithm::RS384,
Self::Rs512Pem(_) => Algorithm::RS512,
}
}
pub(super) fn to_decoding_key(&self) -> std::result::Result<DecodingKey, SecurityError> {
match self {
Self::Hs256(secret) | Self::Hs384(secret) | Self::Hs512(secret) => {
Ok(DecodingKey::from_secret(secret))
},
Self::Rs256Pem(pem) | Self::Rs384Pem(pem) | Self::Rs512Pem(pem) => {
DecodingKey::from_rsa_pem(pem.as_bytes()).map_err(|e| {
SecurityError::SecurityConfigError(format!("Invalid RSA PEM key: {e}"))
})
},
Self::Rs256Components { n, e } => DecodingKey::from_rsa_components(n, e).map_err(|e| {
SecurityError::SecurityConfigError(format!("Invalid RSA components: {e}"))
}),
}
}
}