@@ -122,6 +122,9 @@ impl<G: Group, D: Digest> Client<G, D> {
122122 Self :: new_with_options ( true )
123123 }
124124
125+ /// Create a new SRP client instance, with the ability to override username inclusion in `x`.
126+ ///
127+ /// Set `username_in_x` to false for e.g. compatibility with Apple implementations of SRP.
125128 #[ must_use]
126129 pub fn new_with_options ( username_in_x : bool ) -> Self {
127130 Self {
@@ -131,13 +134,23 @@ impl<G: Group, D: Digest> Client<G, D> {
131134 }
132135 }
133136
134- // v = g^x % N
137+ /// Compute ` g^x % N`, which can be used when computing e.g. `v`.
135138 #[ must_use]
136139 pub fn compute_g_x ( & self , x : & BoxedUint ) -> BoxedUint {
137140 self . g . pow ( x) . retrieve ( )
138141 }
139142
140- // H(<username> | ":" | <raw password>)
143+ /// Get public ephemeral value for handshaking with the server: `g^a % N`.
144+ ///
145+ /// This returns a big endian byte serialization stripped of leading zeros.
146+ #[ must_use]
147+ pub fn compute_public_ephemeral ( & self , a : & [ u8 ] ) -> Vec < u8 > {
148+ self . compute_g_x ( & BoxedUint :: from_be_slice_vartime ( a) )
149+ . to_be_bytes_trimmed_vartime ( )
150+ . into ( )
151+ }
152+
153+ /// Compute the identity hash: `H(<username> | ":" | <raw password>)`.
141154 #[ must_use]
142155 pub fn compute_identity_hash ( username : & [ u8 ] , password : & [ u8 ] ) -> Output < D > {
143156 let mut d = D :: new ( ) ;
@@ -147,7 +160,7 @@ impl<G: Group, D: Digest> Client<G, D> {
147160 d. finalize ( )
148161 }
149162
150- // x = H(<salt> | H(<username> | ":" | <raw password>))
163+ /// Compute ` x = H(<salt> | H(<username> | ":" | <raw password>))`.
151164 #[ must_use]
152165 pub fn compute_x ( identity_hash : & [ u8 ] , salt : & [ u8 ] ) -> BoxedUint {
153166 let mut x = D :: new ( ) ;
@@ -156,7 +169,7 @@ impl<G: Group, D: Digest> Client<G, D> {
156169 BoxedUint :: from_be_slice_vartime ( & x. finalize ( ) )
157170 }
158171
159- // (B - (k * g^x)) ^ (a + (u * x)) % N
172+ /// Compute the premaster secret: ` (B - (k * g^x)) ^ (a + (u * x)) % N`.
160173 #[ must_use]
161174 pub fn compute_premaster_secret (
162175 & self ,
@@ -179,29 +192,22 @@ impl<G: Group, D: Digest> Client<G, D> {
179192 base. pow ( & exp) . retrieve ( )
180193 }
181194
182- /// Get password verifier (v in RFC5054) for user registration on the server.
195+ /// Get password verifier (`v` in RFC5054) for user registration on the server.
183196 #[ must_use]
184197 pub fn compute_verifier ( & self , username : & [ u8 ] , password : & [ u8 ] , salt : & [ u8 ] ) -> Vec < u8 > {
185198 let identity_hash = Self :: compute_identity_hash ( self . identity_username ( username) , password) ;
186199 let x = Self :: compute_x ( identity_hash. as_slice ( ) , salt) ;
187200 self . compute_g_x ( & x) . to_be_bytes_trimmed_vartime ( ) . into ( )
188201 }
189202
190- /// Get public ephemeral value for handshaking with the server.
191- /// g^a % N
192- #[ must_use]
193- pub fn compute_public_ephemeral ( & self , a : & [ u8 ] ) -> Vec < u8 > {
194- self . compute_g_x ( & BoxedUint :: from_be_slice_vartime ( a) )
195- . to_be_bytes_trimmed_vartime ( )
196- . into ( )
197- }
198-
199- /// Process server reply to the handshake according to RFC 5054.
203+ /// Process server reply to the handshake according to [RFC5054].
200204 ///
201205 /// # Params
202206 /// - `a` is a random value,
203207 /// - `username`, `password` is supplied by the user
204208 /// - `salt` and `b_pub` come from the server
209+ ///
210+ /// [RFC5054]: https://datatracker.ietf.org/doc/html/rfc5054
205211 pub fn process_reply (
206212 & self ,
207213 a : & [ u8 ] ,
@@ -325,7 +331,9 @@ impl<G: Group, D: Digest> Default for Client<G, D> {
325331 }
326332}
327333
328- /// RFC 5054 SRP client state after handshake with the server.
334+ /// [RFC5054]-compatible SRP client state after handshake with the server.
335+ ///
336+ /// [RFC5054]: https://datatracker.ietf.org/doc/html/rfc5054
329337pub struct ClientVerifier < D : Digest > {
330338 m1 : Output < D > ,
331339 m2 : Output < D > ,
0 commit comments