cataclysm_jwt/sign_algorithms/
hs256.rs1use std::fmt::Display;
2
3use base64::{Engine as _, engine::general_purpose};
4use ring::hmac::{self, Key};
5
6use crate::error::{Error, JWTError, KeyError};
7
8#[derive(Clone)]
10pub struct HS256 {
11 key: Key
12}
13
14impl HS256 {
15
16 pub fn new<A: AsRef<str>>(secret: A) -> Self {
18
19 let key = hmac::Key::new(hmac::HMAC_SHA256, secret.as_ref().as_bytes());
20 Self {
21 key
22 }
23
24 }
25
26 pub fn sign_jwt(&self, headers: &str, payload: &str) -> String {
30
31 let header_str = general_purpose::URL_SAFE_NO_PAD.encode(headers);
33 let payload_str = general_purpose::URL_SAFE_NO_PAD.encode(payload);
34
35 let unsecure_jwt = format!("{}.{}",header_str,payload_str);
37
38 let sign = general_purpose::URL_SAFE_NO_PAD.encode(hmac::sign(&self.key, unsecure_jwt.as_bytes()).as_ref());
40 format!("{}.{}",unsecure_jwt,sign)
42
43 }
44
45 pub fn verify_jwt(&self, jwt: &str) -> Result<(),Error> {
48
49 let jwt_parts = jwt.split('.').collect::<Vec<&str>>();
51
52 if jwt_parts.len() != 3 {
53 return Err(Error::JWT(JWTError::JWTParts))
54 }
55
56 let headerb64_str = &jwt_parts[0];
58 let payloadb64_str = &jwt_parts[1];
59 let signatureb64 = &jwt_parts[2];
60
61 let unprotected_jwt = format!("{}.{}",headerb64_str,payloadb64_str);
63 let signature = general_purpose::URL_SAFE_NO_PAD.decode(signatureb64).map_err(|e| Error::Decode(e,"Unable to decode signature from jwt"))?;
65
66 hmac::verify(&self.key, unprotected_jwt.as_bytes(), signature.as_ref()).map_err(|e| Error::Key(KeyError::Verification(e)))
69
70 }
71
72}
73
74impl Display for HS256 {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 write!(f,"hs256")
77 }
78}
79
80#[cfg(test)]
81mod test {
82 use crate::{Error, sign_algorithms::HS256};
83
84 #[test]
85 fn verify_signing_hs256() -> Result<(),Error> {
86
87 let header = String::from("{\"Animal\": \"perrito\"}");
88 let payload = String::from("{\"Nombre\": \"Milaneso\"}");
89 let secret = "Doggies";
90
91 let sym_key = HS256::new(secret);
92
93 let secured_jwt = sym_key.sign_jwt(&header,&payload);
94
95 sym_key.verify_jwt(&secured_jwt)
96
97 }
98
99}