@@ -85,7 +85,8 @@ use subtle::ConstantTimeEq;
8585
8686use crate :: types:: { SrpAuthError , SrpGroup } ;
8787use crate :: utils:: {
88- compute_hash, compute_k, compute_m1, compute_m1_rfc5054, compute_m2, compute_u,
88+ compute_hash, compute_k, compute_k_nopad, compute_m1, compute_m1_csrp, compute_m1_rfc5054,
89+ compute_m2, compute_u,
8990} ;
9091
9192/// SRP server state
@@ -126,6 +127,13 @@ impl<'a, D: Digest> SrpServer<'a, D> {
126127 ( inter + self . params . g . modpow ( b, & self . params . n ) ) % & self . params . n
127128 }
128129
130+ // k*v + g^b
131+ #[ must_use]
132+ pub fn compute_b_pub_csrp ( & self , b : & BigUint , k : & BigUint , v : & BigUint ) -> BigUint {
133+ let inter = k * v;
134+ inter + self . params . g . modpow ( b, & self . params . n )
135+ }
136+
129137 // <premaster secret> = (A * v^u) ^ b % N
130138 #[ must_use]
131139 pub fn compute_premaster_secret (
@@ -151,6 +159,16 @@ impl<'a, D: Digest> SrpServer<'a, D> {
151159 . to_bytes_be ( )
152160 }
153161
162+ #[ must_use]
163+ pub fn compute_public_ephemeral_csrp ( & self , b : & [ u8 ] , v : & [ u8 ] ) -> Vec < u8 > {
164+ self . compute_b_pub_csrp (
165+ & BigUint :: from_bytes_be ( b) ,
166+ & compute_k_nopad :: < D > ( self . params ) ,
167+ & BigUint :: from_bytes_be ( v) ,
168+ )
169+ . to_bytes_be ( )
170+ }
171+
154172 /// Process client reply to the handshake.
155173 /// b is a random value,
156174 /// v is the provided during initial user registration
@@ -240,6 +258,56 @@ impl<'a, D: Digest> SrpServer<'a, D> {
240258 session_key : session_key. to_vec ( ) ,
241259 } )
242260 }
261+
262+ /// Process client reply to the handshake according to RFC 5054.
263+ /// b is a random value,
264+ /// v is the provided during initial user registration
265+ pub fn process_reply_csrp (
266+ & self ,
267+ username : & [ u8 ] ,
268+ salt : & [ u8 ] ,
269+ b : & [ u8 ] ,
270+ v : & [ u8 ] ,
271+ a_pub : & [ u8 ] ,
272+ ) -> Result < SrpServerVerifierRfc5054 < D > , SrpAuthError > {
273+ let b = BigUint :: from_bytes_be ( b) ;
274+ let v = BigUint :: from_bytes_be ( v) ;
275+ let a_pub = BigUint :: from_bytes_be ( a_pub) ;
276+
277+ let k = compute_k_nopad :: < D > ( self . params ) ;
278+ let b_pub = self . compute_b_pub_csrp ( & b, & k, & v) ;
279+
280+ // Safeguard against malicious A
281+ if & a_pub % & self . params . n == BigUint :: default ( ) {
282+ return Err ( SrpAuthError :: IllegalParameter ( "a_pub" . to_owned ( ) ) ) ;
283+ }
284+
285+ let u = compute_u :: < D > ( & a_pub. to_bytes_be ( ) , & b_pub. to_bytes_be ( ) ) ;
286+
287+ let premaster_secret = self
288+ . compute_premaster_secret ( & a_pub, & v, & u, & b)
289+ . to_bytes_be ( ) ;
290+
291+ let session_key = compute_hash :: < D > ( & premaster_secret) ;
292+
293+ let m1 = compute_m1_csrp :: < D > (
294+ self . params ,
295+ username,
296+ salt,
297+ & a_pub. to_bytes_be ( ) ,
298+ & b_pub. to_bytes_be ( ) ,
299+ session_key. as_slice ( ) ,
300+ ) ;
301+
302+ let m2 = compute_m2 :: < D > ( & a_pub. to_bytes_be ( ) , & m1, session_key. as_slice ( ) ) ;
303+
304+ Ok ( SrpServerVerifierRfc5054 {
305+ m1,
306+ m2,
307+ key : premaster_secret,
308+ session_key : session_key. to_vec ( ) ,
309+ } )
310+ }
243311}
244312
245313impl < D : Digest > SrpServerVerifier < D > {
0 commit comments