ftth_rsip/services/
digest_generator.rs1use crate::{
2 common::{uri::Uri, Method},
3 headers::{
4 self,
5 auth::{Algorithm, AuthQop},
6 },
7};
8
9#[derive(Debug, Clone)]
16pub struct DigestGenerator<'a> {
17 pub username: &'a str,
18 pub password: &'a str,
19 pub nonce: &'a str,
20 pub uri: &'a Uri,
21 pub realm: &'a str,
22 pub method: &'a Method,
23 pub qop: Option<&'a AuthQop>,
24 pub algorithm: Algorithm,
25}
26
27impl<'a> DigestGenerator<'a> {
28 pub fn from(
30 auth: &'a headers::typed::Authorization,
31 password: &'a str,
32 method: &'a Method,
33 ) -> Self {
34 Self {
35 username: &auth.username,
36 password,
37 nonce: &auth.nonce,
38 uri: &auth.uri,
39 realm: &auth.realm,
40 method,
41 qop: auth.qop.as_ref(),
42 algorithm: auth.algorithm.unwrap_or(Algorithm::Md5),
43 }
44 }
45
46 pub fn verify(&self, response: &'a str) -> bool {
47 self.compute() == response
48 }
49
50 pub fn compute(&self) -> String {
51 let value = match self.qop {
52 Some(AuthQop::Auth { cnonce, nc }) => format!(
53 "{}:{}:{:08}:{}:{}:{}",
54 self.ha1(),
55 self.nonce,
56 nc,
57 cnonce,
58 "auth",
59 self.ha2()
60 ),
61 Some(AuthQop::AuthInt { cnonce, nc }) => format!(
62 "{}:{}:{:08}:{}:{}:{}",
63 self.ha1(),
64 self.nonce,
65 nc,
66 cnonce,
67 "auth-int",
68 self.ha2()
69 ),
70 None => format!("{}:{}:{}", self.ha1(), self.nonce, self.ha2()),
71 };
72
73 self.hash_value(value)
74 }
75
76 fn ha1(&self) -> String {
77 let value = format!("{}:{}:{}", self.username, self.realm, self.password);
78
79 self.hash_value(value)
80 }
81
82 fn ha2(&self) -> String {
83 let value = match self.qop {
84 None | Some(AuthQop::Auth { .. }) => format!("{}:{}", self.method, self.uri),
85 _ => format!(
86 "{}:{}:d41d8cd98f00b204e9800998ecf8427e",
87 self.method, self.uri
88 ),
89 };
90
91 self.hash_value(value)
92 }
93
94 fn hash_value(&self, value: String) -> String {
95 use md5::{Digest, Md5};
96 use sha2::{Sha256, Sha512};
97
98 match self.algorithm {
99 Algorithm::Md5 | Algorithm::Md5Sess => {
100 let mut hasher = Md5::new();
101 hasher.update(value);
102 format!("{:x}", hasher.finalize())
103 }
104 Algorithm::Sha256 | Algorithm::Sha256Sess => {
105 let mut hasher = Sha256::new();
106 hasher.update(value);
107 format!("{:x}", hasher.finalize())
108 }
109 Algorithm::Sha512 | Algorithm::Sha512Sess => {
110 let mut hasher = Sha512::new();
111 hasher.update(value);
112 format!("{:x}", hasher.finalize())
113 }
114 }
115 }
116}