Skip to content

Commit 2df2cf1

Browse files
authored
srp: rename and deprecate legacy implementation (#237)
Attempts to steer people towards the new RFC5054-compatible implementation by adding `*_legacy` and `Legacy*` to methods and types for the `srp` v0.6-and-earlier compatible implementation. Ideally it can be removed in the next breaking release after this one, and we can only support RFC5054. But for now, this makes a migration possible.
1 parent 86fa82e commit 2df2cf1

File tree

4 files changed

+161
-132
lines changed

4 files changed

+161
-132
lines changed

srp/src/client.rs

Lines changed: 58 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@
4040
//! # let b_pub = b"b_pub";
4141
//!
4242
//! let private_key = (username, password, salt);
43-
//! let verifier = client.process_reply(&a, username, password, salt, b_pub);
43+
//! let verifier = client.process_reply_legacy(&a, username, password, salt, b_pub);
4444
//! ```
4545
//!
4646
//! Finally verify the server: first generate user proof,
@@ -61,7 +61,7 @@
6161
//! key using `key()` method.
6262
//! ```rust
6363
//! # let client = srp::Client::<srp::G2048, sha2::Sha256>::new();
64-
//! # let verifier = client.process_reply(b"", b"", b"", b"", b"1").unwrap();
64+
//! # let verifier = client.process_reply_legacy(b"", b"", b"", b"", b"1").unwrap();
6565
//!
6666
//! verifier.key();
6767
//! ```
@@ -200,18 +200,20 @@ impl<G: Group, D: Digest> Client<G, D> {
200200
.into()
201201
}
202202

203-
/// Process server reply to the handshake.
203+
/// Process server reply to the handshake according to RFC 5054.
204+
///
205+
/// # Params
204206
/// `a` is a random value,
205207
/// `username`, `password` is supplied by the user
206208
/// `salt` and `b_pub` come from the server
207-
pub fn process_reply(
209+
pub fn process_reply_rfc5054(
208210
&self,
209211
a: &[u8],
210212
username: &[u8],
211213
password: &[u8],
212214
salt: &[u8],
213215
b_pub: &[u8],
214-
) -> Result<ClientVerifier<D>, AuthError> {
216+
) -> Result<ClientVerifierRfc5054<D>, AuthError> {
215217
let a = BoxedUint::from_be_slice_vartime(a);
216218
let a_pub = self.compute_g_x(&a);
217219
let b_pub = BoxedUint::from_be_slice_vartime(b_pub);
@@ -227,39 +229,57 @@ impl<G: Group, D: Digest> Client<G, D> {
227229
let identity_hash = Self::compute_identity_hash(self.identity_username(username), password);
228230
let x = Self::compute_x(identity_hash.as_slice(), salt);
229231

230-
let key = self.compute_premaster_secret(&b_pub, &k, &x, &a, &u);
232+
let premaster_secret = self
233+
.compute_premaster_secret(&b_pub, &k, &x, &a, &u)
234+
.to_be_bytes_trimmed_vartime();
231235

232-
let m1 = compute_m1::<D>(
236+
let session_key = compute_hash::<D>(&premaster_secret);
237+
238+
let m1 = compute_m1_rfc5054::<D>(
239+
&self.g,
240+
username,
241+
salt,
233242
&a_pub.to_be_bytes_trimmed_vartime(),
234243
&b_pub.to_be_bytes_trimmed_vartime(),
235-
&key.to_be_bytes_trimmed_vartime(),
244+
session_key.as_slice(),
236245
);
237246

238247
let m2 = compute_m2::<D>(
239248
&a_pub.to_be_bytes_trimmed_vartime(),
240249
&m1,
241-
&key.to_be_bytes_trimmed_vartime(),
250+
session_key.as_slice(),
242251
);
243252

244-
Ok(ClientVerifier {
253+
Ok(ClientVerifierRfc5054 {
245254
m1,
246255
m2,
247-
key: key.to_be_bytes_trimmed_vartime().to_vec(),
256+
key: premaster_secret.to_vec(),
257+
session_key: session_key.to_vec(),
248258
})
249259
}
250260

251-
/// Process server reply to the handshake according to RFC 5054.
252-
/// `a` is a random value,
253-
/// `username`, `password` is supplied by the user
254-
/// `salt` and `b_pub` come from the server
255-
pub fn process_reply_rfc5054(
261+
/// Process server reply to the handshake using the legacy implementation.
262+
///
263+
/// This implementation is compatible with `srp` v0.6 and earlier. Note the default
264+
/// implementation is now RFC5054 compatible.
265+
///
266+
/// # Params
267+
/// - `a` is a random value,
268+
/// - `username`, `password` is supplied by the user
269+
/// - `salt` and `b_pub` come from the server
270+
#[deprecated(
271+
since = "0.7.0",
272+
note = "please switch to `Client::process_reply_rfc5054`"
273+
)]
274+
#[allow(deprecated)]
275+
pub fn process_reply_legacy(
256276
&self,
257277
a: &[u8],
258278
username: &[u8],
259279
password: &[u8],
260280
salt: &[u8],
261281
b_pub: &[u8],
262-
) -> Result<ClientVerifierRfc5054<D>, AuthError> {
282+
) -> Result<LegacyClientVerifier<D>, AuthError> {
263283
let a = BoxedUint::from_be_slice_vartime(a);
264284
let a_pub = self.compute_g_x(&a);
265285
let b_pub = BoxedUint::from_be_slice_vartime(b_pub);
@@ -275,32 +295,24 @@ impl<G: Group, D: Digest> Client<G, D> {
275295
let identity_hash = Self::compute_identity_hash(self.identity_username(username), password);
276296
let x = Self::compute_x(identity_hash.as_slice(), salt);
277297

278-
let premaster_secret = self
279-
.compute_premaster_secret(&b_pub, &k, &x, &a, &u)
280-
.to_be_bytes_trimmed_vartime();
281-
282-
let session_key = compute_hash::<D>(&premaster_secret);
298+
let key = self.compute_premaster_secret(&b_pub, &k, &x, &a, &u);
283299

284-
let m1 = compute_m1_rfc5054::<D>(
285-
&self.g,
286-
username,
287-
salt,
300+
let m1 = compute_m1::<D>(
288301
&a_pub.to_be_bytes_trimmed_vartime(),
289302
&b_pub.to_be_bytes_trimmed_vartime(),
290-
session_key.as_slice(),
303+
&key.to_be_bytes_trimmed_vartime(),
291304
);
292305

293306
let m2 = compute_m2::<D>(
294307
&a_pub.to_be_bytes_trimmed_vartime(),
295308
&m1,
296-
session_key.as_slice(),
309+
&key.to_be_bytes_trimmed_vartime(),
297310
);
298311

299-
Ok(ClientVerifierRfc5054 {
312+
Ok(LegacyClientVerifier {
300313
m1,
301314
m2,
302-
key: premaster_secret.to_vec(),
303-
session_key: session_key.to_vec(),
315+
key: key.to_be_bytes_trimmed_vartime().to_vec(),
304316
})
305317
}
306318

@@ -338,14 +350,15 @@ impl<G: Group, D: Digest> Default for Client<G, D> {
338350
}
339351
}
340352

341-
/// SRP client state after handshake with the server.
342-
pub struct ClientVerifier<D: Digest> {
353+
/// RFC 5054 SRP client state after handshake with the server.
354+
pub struct ClientVerifierRfc5054<D: Digest> {
343355
m1: Output<D>,
344356
m2: Output<D>,
345357
key: Vec<u8>,
358+
session_key: Vec<u8>,
346359
}
347360

348-
impl<D: Digest> ClientVerifier<D> {
361+
impl<D: Digest> ClientVerifierRfc5054<D> {
349362
/// Get shared secret key without authenticating server, e.g. for using with
350363
/// authenticated encryption modes. DO NOT USE this method without
351364
/// some kind of secure authentication
@@ -358,25 +371,26 @@ impl<D: Digest> ClientVerifier<D> {
358371
self.m1.as_slice()
359372
}
360373

361-
/// Verify server reply to verification data.
362-
pub fn verify_server(&self, reply: &[u8]) -> Result<(), AuthError> {
374+
/// Verify server reply to verification data and return shared session key.
375+
pub fn verify_server(&self, reply: &[u8]) -> Result<&[u8], AuthError> {
363376
if self.m2.ct_eq(reply).unwrap_u8() == 1 {
364-
Ok(())
377+
Ok(self.session_key.as_slice())
365378
} else {
366379
Err(AuthError::BadRecordMac { peer: "server" })
367380
}
368381
}
369382
}
370383

371-
/// RFC 5054 SRP client state after handshake with the server.
372-
pub struct ClientVerifierRfc5054<D: Digest> {
384+
/// Legacy SRP client state after handshake with the server, compatible with `srp` v0.6 and earlier.
385+
#[deprecated(since = "0.7.0", note = "please switch to `ClientVerifierRfc5054`")]
386+
pub struct LegacyClientVerifier<D: Digest> {
373387
m1: Output<D>,
374388
m2: Output<D>,
375389
key: Vec<u8>,
376-
session_key: Vec<u8>,
377390
}
378391

379-
impl<D: Digest> ClientVerifierRfc5054<D> {
392+
#[allow(deprecated)]
393+
impl<D: Digest> LegacyClientVerifier<D> {
380394
/// Get shared secret key without authenticating server, e.g. for using with
381395
/// authenticated encryption modes. DO NOT USE this method without
382396
/// some kind of secure authentication
@@ -389,10 +403,10 @@ impl<D: Digest> ClientVerifierRfc5054<D> {
389403
self.m1.as_slice()
390404
}
391405

392-
/// Verify server reply to verification data and return shared session key.
393-
pub fn verify_server(&self, reply: &[u8]) -> Result<&[u8], AuthError> {
406+
/// Verify server reply to verification data.
407+
pub fn verify_server(&self, reply: &[u8]) -> Result<(), AuthError> {
394408
if self.m2.ct_eq(reply).unwrap_u8() == 1 {
395-
Ok(self.session_key.as_slice())
409+
Ok(())
396410
} else {
397411
Err(AuthError::BadRecordMac { peer: "server" })
398412
}

0 commit comments

Comments
 (0)