rustauth_core/cookies/
signing.rs1use base64::engine::general_purpose::STANDARD;
2use base64::Engine;
3use hmac::{Hmac, Mac};
4use sha2::Sha256;
5
6use crate::error::RustAuthError;
7
8pub(super) fn hmac_base64(value: &str, secret: &str) -> Result<String, RustAuthError> {
9 let mut mac = Hmac::<Sha256>::new_from_slice(secret.as_bytes())
10 .map_err(|error| RustAuthError::Cookie(error.to_string()))?;
11 mac.update(value.as_bytes());
12 Ok(STANDARD.encode(mac.finalize().into_bytes()))
13}
14
15pub fn sign_cookie_value(value: &str, secret: &str) -> Result<String, RustAuthError> {
16 Ok(format!("{value}.{}", hmac_base64(value, secret)?))
17}
18
19pub fn verify_cookie_value(value: &str, secret: &str) -> Result<Option<String>, RustAuthError> {
20 let Some((unsigned, signature)) = value.rsplit_once('.') else {
21 return Ok(None);
22 };
23 let expected = hmac_base64(unsigned, secret)?;
24 if crate::crypto::buffer::constant_time_equal(expected.as_bytes(), signature.as_bytes()) {
25 Ok(Some(unsigned.to_owned()))
26 } else {
27 Ok(None)
28 }
29}