1use base64::Engine;
9use digest::Digest;
10use srp::client::{SrpClient, SrpClientVerifier};
11use getrandom::getrandom;
12
13#[cfg(feature = "serde")]
14use serde::{Serialize, Deserialize};
15
16use crate::types::Result;
17
18pub struct ClientAuthenticationWorkflow<'c, D: Digest> {
25 delegate: SrpClient<'c, D>,
26}
27
28impl<'c, D: Digest> ClientAuthenticationWorkflow<'c, D> {
29 pub fn new(group: &'c crate::groups::SrpGroup) -> Self {
34 return Self {
35 delegate: SrpClient::<'c, D>::new(group),
36 };
37 }
38
39 pub fn step1(&self) -> Result<ClientStep1Result> {
49 let mut client_private_a = vec![0 as u8; 128];
50 getrandom(client_private_a.as_mut_slice())?;
51
52 let client_public_a = self.delegate.compute_public_ephemeral(client_private_a.as_slice());
53
54 return Ok(ClientStep1Result {
55 client_private_a,
56 client_public_a
57 });
58 }
59
60 pub fn step3(&self, params: ClientStep3Params) -> Result<ClientStep3Result<D>> {
66 let verifier = self.delegate.process_reply(
67 params.client_a,
68 params.username.as_bytes(),
69 params.password.as_bytes(),
70 params.salt,
71 params.server_public_b
72 )?;
73
74 return Ok(ClientStep3Result {
75 verifier
76 });
77 }
78
79 }
81
82#[derive(Debug, Clone)]
86#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
87pub struct ClientStep1Result {
88 #[serde(with = "crate::util::base64_vec_u8")]
90 pub client_private_a: Vec<u8>,
91
92 #[serde(with = "crate::util::base64_vec_u8")]
94 pub client_public_a: Vec<u8>,
95}
96
97#[derive(Debug, Clone)]
101#[cfg_attr(feature = "serde", derive(Serialize))]
102pub struct ClientStep3Params<'p> {
103 #[serde(with = "crate::util::base64_u8")]
105 pub client_a: &'p [u8],
106
107 pub username: String,
109
110 pub password: String,
112
113 #[serde(with = "crate::util::base64_u8")]
115 pub salt: &'p [u8],
116
117 #[serde(with = "crate::util::base64_u8")]
119 pub server_public_b: &'p [u8],
120}
121
122pub struct ClientStep3Result<D: Digest> {
127 verifier: SrpClientVerifier<D>,
128}
129
130impl<D: Digest> ClientStep3Result<D> {
131 pub fn key(&self) -> &[u8] {
136 return self.verifier.key();
137 }
138
139 pub fn proof(&self) -> &[u8] {
144 return self.verifier.proof();
145 }
146
147 pub fn verify_server(&self, proof: &[u8]) -> Result<()> {
152 return self.verifier.verify_server(proof)
153 .or_else(|err| Err(err.into()));
154 }
155}
156
157pub struct ClientRegistrationWorkflow<'c, D: Digest> {
164 delegate: SrpClient<'c, D>,
165}
166
167impl<'c, D: Digest> ClientRegistrationWorkflow<'c, D> {
168 pub fn new(group: &'c crate::groups::SrpGroup) -> Self {
173 return Self {
174 delegate: SrpClient::<'c, D>::new(group),
175 };
176 }
177
178 pub fn generate_verifier(&self, params: GenerateVerifierParams) -> Result<Verifier> {
184 let GenerateVerifierParams {
185 username,
186 password,
187 salt
188 } = params;
189
190 let salt = if let Some(salt) = salt {
191 salt
192 } else {
193 let mut random_salt = vec![0 as u8; 32];
194 getrandom::getrandom(random_salt.as_mut_slice())?;
195 random_salt
196 };
197
198 let verifier = self.delegate.compute_verifier(
199 username.as_bytes(),
200 password.as_bytes(),
201 salt.as_slice());
202
203 return Ok(Verifier {
204 username,
205 salt,
206 verifier
207 });
208 }
209}
210
211#[derive(Debug, Clone)]
213#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
214pub struct GenerateVerifierParams {
215 pub username: String,
217
218 pub password: String,
222
223 #[serde(with = "crate::util::base64_opt_vec_u8")]
228 pub salt: Option<Vec<u8>>,
229}
230
231#[derive(Debug, Clone)]
235#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
236pub struct Verifier {
237 pub username: String,
238 #[serde(with = "crate::util::base64_vec_u8")]
239 pub salt: Vec<u8>,
240 #[serde(with = "crate::util::base64_vec_u8")]
241 pub verifier: Vec<u8>,
242}
243
244#[cfg(feature = "base64")]
245impl Verifier {
246 pub fn salt_base64(&self) -> String {
247 let engine = base64::engine::general_purpose::STANDARD_NO_PAD;
248 let result = engine.encode(self.salt.as_slice());
249 return result;
250 }
251
252 pub fn verifier_base64(&self) -> String {
253 let engine = base64::engine::general_purpose::STANDARD_NO_PAD;
254 let result = engine.encode(self.verifier.as_slice());
255 return result;
256 }
257}