ultimate_common/
digest.rs1use base64ct::{Base64UrlUnpadded, Encoding};
2pub use hmac::digest::InvalidLength;
3use hmac::{
4 digest::{
5 generic_array::GenericArray,
6 typenum::{UInt, UTerm, B0, B1},
7 CtOutput,
8 },
9 Hmac, Mac,
10};
11use sha2::{Digest, Sha256};
12
13use crate::Error;
14
15type HmacSha256 = Hmac<Sha256>;
16
17pub fn hmac_sha256(secret: &[u8], s: &[u8]) -> Result<CtOutput<HmacSha256>, InvalidLength> {
18 let mut mac = HmacSha256::new_from_slice(secret)?;
19 mac.update(s);
20 let result = mac.finalize();
21 Ok(result)
22}
23
24#[inline]
25pub fn hmac_sha256_string(secret: &[u8], s: &[u8]) -> Result<String, InvalidLength> {
26 let bytes = hmac_sha256(secret, s)?.into_bytes();
27 Ok(base16ct::lower::encode_string(&bytes))
28}
29
30type ShaArray = GenericArray<u8, UInt<UInt<UInt<UInt<UInt<UInt<UTerm, B1>, B0>, B0>, B0>, B0>, B0>>;
31
32pub fn sha256(s: &[u8]) -> ShaArray {
33 let mut hasher: Sha256 = Sha256::new();
34 hasher.update(s);
35 hasher.finalize()
36}
37
38#[inline]
39pub fn sha256_string(s: &[u8]) -> String {
40 let result = sha256(s);
41 base16ct::lower::encode_string(&result)
42}
43
44pub fn b64u_encode(content: impl AsRef<[u8]>) -> String {
45 Base64UrlUnpadded::encode_string(content.as_ref())
46}
47
48pub fn b64u_decode(b64u: &str) -> Result<Vec<u8>, Error> {
49 Base64UrlUnpadded::decode_vec(b64u).map_err(|_| Error::FailToB64uDecode(b64u.to_string()))
50}
51
52pub fn b64u_decode_to_string(b64u: &str) -> Result<String, Error> {
53 b64u_decode(b64u).ok().and_then(|r| String::from_utf8(r).ok()).ok_or(Error::FailToB64uDecode(b64u.to_string()))
54}