//! First receive user's username and public value `a_pub`, retrieve from a
//! database `UserRecord` for a given username, generate `b` (e.g. 512 bits
//! long) and initialize SRP server instance:
-//!
+//!
//! ```ignore
//! use srp::groups::G_2048;
//!
//! let b = rng.gen_iter::<u8>().take(64).collect::<Vec<u8>>();
//! let server = SrpServer::<Sha256>::new(&user, &a_pub, &b, &G_2048)?;
//! ```
-//!
+//!
//! Next send to user `b_pub` and `salt` from user record:
-//!
+//!
//! ```ignore
//! let b_pub = server.get_b_pub();
//! conn.reply_to_handshake(&user.salt, b_pub);
//! ```
-//!
+//!
//! And finally recieve user proof, verify it and send server proof in the
//! reply:
-//!
+//!
//! ```ignore
//! let user_proof = conn.receive_proof();
//! let server_proof = server.verify(user_proof)?;
//! conn.send_proof(server_proof);
//! ```
-//!
+//!
//! To get the shared secret use `get_key` method. As alternative to using
//! `verify` method it's also possible to use this key for authentificated
//! encryption.
use std::marker::PhantomData;
-use num::{BigUint, Zero};
use digest::Digest;
use generic_array::GenericArray;
+use num::{BigUint, Zero};
use tools::powm;
use types::{SrpAuthError, SrpGroup};
key: GenericArray<u8, D::OutputSize>,
- d: PhantomData<D>
+ d: PhantomData<D>,
}
-impl< D: Digest> SrpServer< D> {
+impl<D: Digest> SrpServer<D> {
/// Create new server state.
- pub fn new(user: &UserRecord, a_pub: &[u8], b: &[u8], params: &SrpGroup)
- -> Result<Self, SrpAuthError>
- {
+ pub fn new(
+ user: &UserRecord,
+ a_pub: &[u8],
+ b: &[u8],
+ params: &SrpGroup,
+ ) -> Result<Self, SrpAuthError> {
let a_pub = BigUint::from_bytes_be(a_pub);
// Safeguard against malicious A
if &a_pub % ¶ms.n == BigUint::zero() {
- return Err(SrpAuthError { description: "Malicious a_pub value" })
+ return Err(SrpAuthError {
+ description: "Malicious a_pub value",
+ });
}
let v = BigUint::from_bytes_be(user.verifier);
- let b = BigUint::from_bytes_be(b) % ¶ms.n;
+ let b = BigUint::from_bytes_be(b) % ¶ms.n;
let k = params.compute_k::<D>();
// kv + g^b
let interm = (k * &v) % ¶ms.n;
let d = Default::default();
//(Av^u) ^ b
let key = {
- let u = BigUint::from_bytes_be(&u);
+ let u = BigUint::from_bytes_be(&u);
let t = (&a_pub * powm(&v, &u, ¶ms.n)) % ¶ms.n;
let s = powm(&t, &b, ¶ms.n);
D::digest(&s.to_bytes_be())
};
- Ok(Self { b, a_pub, b_pub, key, d})
+ Ok(Self {
+ b,
+ a_pub,
+ b_pub,
+ key,
+ d,
+ })
}
/// Get private `b` value. (see `new_with_b` documentation)
/// Process user proof of having the same shared secret and compute
/// server proof for sending to the user.
- pub fn verify(&self, user_proof: &[u8])
- -> Result<GenericArray<u8, D::OutputSize>, SrpAuthError>
- {
+ pub fn verify(
+ &self,
+ user_proof: &[u8],
+ ) -> Result<GenericArray<u8, D::OutputSize>, SrpAuthError> {
// M = H(A, B, K)
let mut d = D::new();
d.input(&self.a_pub.to_bytes_be());
d.input(&self.key);
Ok(d.result())
} else {
- Err(SrpAuthError { description: "Incorrect user proof" })
+ Err(SrpAuthError {
+ description: "Incorrect user proof",
+ })
}
}
}