diff options
Diffstat (limited to 'src/server.rs')
-rw-r--r-- | src/server.rs | 61 |
1 files changed, 25 insertions, 36 deletions
diff --git a/src/server.rs b/src/server.rs index e82ebf6..137d6b3 100644 --- a/src/server.rs +++ b/src/server.rs @@ -2,13 +2,16 @@ //! //! # Usage //! First receive user's username and public value `a_pub`, retrieve from a -//! database `UserRecord` for a given username and initialize SRP server state: +//! database `UserRecord` for a given username, generate `b` (e.g. 512 bits +//! long) and initialize SRP server instance: //! //! ```ignore -//! let mut rng = rand::os::OsRng::new().unwrap(); +//! use srp::groups::G_2048; +//! //! let (username, a_pub) = conn.receive_handshake(); //! let user = db.retrieve_user_record(username); -//! let server = SrpServer::<Sha256>::new(&user, &a_pub, &srp_params, &mut rng)?; +//! 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: @@ -18,7 +21,8 @@ //! conn.reply_to_handshake(&user.salt, b_pub); //! ``` //! -//! And finally recieve user proof, verify it and send server proof as reply: +//! And finally recieve user proof, verify it and send server proof in the +//! reply: //! //! ```ignore //! let user_proof = conn.receive_proof(); @@ -31,13 +35,12 @@ //! encryption. use std::marker::PhantomData; -use rand::Rng; use num::{BigUint, Zero}; use digest::Digest; use generic_array::GenericArray; use tools::powm; -use types::{SrpAuthError, SrpParams}; +use types::{SrpAuthError, SrpGroup}; /// Data provided by users upon registration, usually stored in the database. pub struct UserRecord<'a> { @@ -59,61 +62,47 @@ pub struct SrpServer<D: Digest> { } impl< D: Digest> SrpServer< D> { - /// Create new server state with randomly generated `b`. - pub fn new<R: Rng>(user: &UserRecord, a_pub: &[u8], params: &SrpParams, - rng: &mut R) - -> Result<Self, SrpAuthError> - { - let l = params.n.bits()/8; - let b = rng.gen_iter::<u8>().take(l).collect::<Vec<u8>>(); - Self::new_with_b(user, a_pub, &b, params) - } - - /// Create new server state with given `b`. - /// - /// Usefull if it's not convenient to keep `SrpServer` state between - /// handshake and verification steps. (e.g. when working over HTTP and - /// storing `b` in a database) - pub fn new_with_b(user: &UserRecord, a_pub: &[u8], b: &[u8], - params: &SrpParams) + /// Create new server state. + pub fn new(user: &UserRecord, a_pub: &[u8], b: &[u8], params: &SrpGroup) -> Result<Self, SrpAuthError> { - let a_pub = BigUint::from_bytes_le(a_pub); + 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" }) } - let v = BigUint::from_bytes_le(user.verifier); - let b = BigUint::from_bytes_le(b) % ¶ms.n; + let v = BigUint::from_bytes_be(user.verifier); + let b = BigUint::from_bytes_be(b) % ¶ms.n; + let k = params.compute_k::<D>(); // kv + g^b - let interm = (¶ms.k * &v) % ¶ms.n; + let interm = (k * &v) % ¶ms.n; let b_pub = (interm + ¶ms.powm(&b)) % ¶ms.n; // H(A || B) let u = { let mut d = D::new(); - d.input(&a_pub.to_bytes_le()); - d.input(&b_pub.to_bytes_le()); + d.input(&a_pub.to_bytes_be()); + d.input(&b_pub.to_bytes_be()); d.result() }; let d = Default::default(); //(Av^u) ^ b let key = { - let u = BigUint::from_bytes_le(&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_le()) + D::digest(&s.to_bytes_be()) }; Ok(Self { b, a_pub, b_pub, key, d}) } /// Get private `b` value. (see `new_with_b` documentation) pub fn get_b(&self) -> Vec<u8> { - self.b.to_bytes_le() + self.b.to_bytes_be() } /// Get public `b_pub` value for sending to the user. pub fn get_b_pub(&self) -> Vec<u8> { - self.b_pub.to_bytes_le() + self.b_pub.to_bytes_be() } /// Get shared secret between user and the server. (do not forget to verify @@ -129,14 +118,14 @@ impl< D: Digest> SrpServer< D> { { // M = H(A, B, K) let mut d = D::new(); - d.input(&self.a_pub.to_bytes_le()); - d.input(&self.b_pub.to_bytes_le()); + d.input(&self.a_pub.to_bytes_be()); + d.input(&self.b_pub.to_bytes_be()); d.input(&self.key); if user_proof == d.result().as_slice() { // H(A, M, K) let mut d = D::new(); - d.input(&self.a_pub.to_bytes_le()); + d.input(&self.a_pub.to_bytes_be()); d.input(user_proof); d.input(&self.key); Ok(d.result()) |