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}