easy_srp/server.rs
1//! Server-side SRP implementation
2//!
3//! Contains the `ServerAuthenticationWorkflow` for implementing the server
4//! side of the SRP authentication.
5
6use digest::Digest;
7use serde::Serialize;
8use srp::server::{SrpServer, SrpServerVerifier};
9use getrandom::getrandom;
10
11use crate::types::Result;
12
13/// Server-side of the authentication workflow
14///
15/// This struct should be used on the server side to authenticate a
16/// compatible SRP6a client.
17/// Digest `D` specifies the digest algorithm used and therefore also implicitly
18/// defines the key size of the common secret key.
19pub struct ServerAuthenticationWorkflow<'s, D: Digest> {
20 delegate: SrpServer<'s, D>,
21}
22
23impl<'s, D: Digest> ServerAuthenticationWorkflow<'s, D> {
24 pub fn new(group: &'s crate::groups::SrpGroup) -> Self {
25 return Self {
26 delegate: SrpServer::<'s, D>::new(group),
27 };
28 }
29
30 /// step2: server creates ephemeral key from random bytes and stored verifier
31 ///
32 /// The private key `server_private_b` must not be exposed, but needs to
33 /// be stored for future steps.
34 /// The public key `server_public_b` and the `salt` must be sent to the
35 /// client.
36 ///
37 /// receive: `client_public_a` from client
38 /// keep: `server_private_a`, `client_public_b`
39 /// send: `server_public_a`, `salt` to client
40 pub fn step2(&self, params: ServerStep2Params) -> Result<ServerStep2Result> {
41 let mut server_private_b = vec![0 as u8; 128];
42 getrandom(server_private_b.as_mut_slice())?;
43
44 let server_public_b = self.delegate.compute_public_ephemeral(
45 server_private_b.as_slice(),
46 params.stored_verifier);
47
48 return Ok(ServerStep2Result {
49 server_private_b,
50 server_public_b
51 });
52 }
53
54 /// step4: server-side: generate verifier
55 ///
56 /// the `proof()` of the result should be sent to the client
57 pub fn step4(&self, params: ServerStep4Params) -> Result<ServerStep4Result<D>> {
58 let verifier = self.delegate.process_reply(
59 params.server_private_b,
60 params.stored_verifier,
61 params.client_public_a)?;
62
63 verifier.verify_client(params.client_proof)?;
64
65 return Ok(ServerStep4Result {
66 verifier
67 });
68 }
69
70 // step 6: client verifies proof
71
72}
73
74/// Parameters for step 2
75#[derive(Debug, Clone)]
76#[cfg_attr(feature = "serde", derive(Serialize))]
77pub struct ServerStep2Params<'p> {
78 /// The verifier stored for the given user
79 ///
80 /// Contains the verifier that has been stored for the given user during
81 /// user registration.
82 #[serde(with = "crate::util::base64_u8")]
83 pub stored_verifier: &'p [u8],
84}
85
86// Result of step 2
87#[derive(Debug, Clone)]
88#[cfg_attr(feature = "serde", derive(Serialize))]
89pub struct ServerStep2Result {
90 /// The server's private ephemeral key
91 ///
92 /// This must be kept secret.
93 #[serde(with = "crate::util::base64_vec_u8")]
94 pub server_private_b: Vec<u8>,
95
96 /// The server's public ephemeral key
97 ///
98 /// This must be sent to the client.
99 #[serde(with = "crate::util::base64_vec_u8")]
100 pub server_public_b: Vec<u8>,
101}
102
103/// Parameters for step 4
104///
105/// Step 4 verifies the client proof.
106#[derive(Debug, Clone)]
107#[cfg_attr(feature = "serde", derive(Serialize))]
108pub struct ServerStep4Params<'p> {
109 /// The server's private ephemeral key generated in step 2
110 #[serde(with = "crate::util::base64_u8")]
111 pub server_private_b: &'p [u8],
112
113 /// The verifier stored for the user during user registration
114 #[serde(with = "crate::util::base64_u8")]
115 pub stored_verifier: &'p [u8],
116
117 /// The client's public key received as part of step 2
118 #[serde(with = "crate::util::base64_u8")]
119 pub client_public_a: &'p [u8],
120
121 /// The client's proof
122 ///
123 /// Verifying the client proof is a prerequesite for sending any encrypted
124 /// data (including the server proof) to the client. Not verifying the
125 /// client proof may enable brute force attacks on the user credentials.
126 #[serde(with = "crate::util::base64_u8")]
127 pub client_proof: &'p [u8],
128}
129
130/// Result of step 4
131///
132/// The result of step 4 can be used to verify the client's proof and
133/// to generate a client proof, as well as to generate the common key.
134pub struct ServerStep4Result<D: Digest> {
135 verifier: SrpServerVerifier<D>,
136}
137
138impl<D: Digest> ServerStep4Result<D> {
139 /// Get the common secret key
140 ///
141 /// SRP6a authentication results in a secret key shared by the client
142 /// and server.
143 pub fn key(&self) -> &[u8] {
144 return self.verifier.key();
145 }
146
147 /// Generate a server proof
148 ///
149 /// The generated value can be used to proof to the client that the server
150 /// is using the same secret key.
151 pub fn proof(&self) -> &[u8] {
152 return self.verifier.proof();
153 }
154
155 /// Verify the client's proof
156 ///
157 /// This method verifies the the client's `proof` is correct, thereby
158 /// verifying that the client uses the same secret key as the server.
159 pub fn verify_client(&self, reply: &[u8]) -> Result<()> {
160 return self.verifier.verify_client(reply)
161 .or_else(|err| Err(err.into()));
162 }
163}