aboutsummaryrefslogtreecommitdiff
path: root/src/client.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/client.rs')
-rw-r--r--src/client.rs57
1 files changed, 29 insertions, 28 deletions
diff --git a/src/client.rs b/src/client.rs
index ee19e88..87990a6 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -2,12 +2,14 @@
//!
//! # Usage
//! First create SRP client struct by passing to it SRP parameters (shared
-//! between client and server) and RNG instance (OS RNG is recommended):
+//! between client and server) and randomly generated `a`:
//!
//! ```ignore
-//! let srp_params = SrpParams{n, g, k};
-//! let mut rng = rand::os::OsRng::new().unwrap();
-//! let client = SrpClient::<Sha256>::new(&srp_params, &mut rng);
+//! use srp::groups::G_2048;
+//! use sha2::Sha256;
+//!
+//! let a = rng.gen_iter::<u8>().take(64).collect::<Vec<u8>>();
+//! let client = SrpClient::<Sha256>::new(&a, &srp_params);
//! ```
//!
//! Next send handshake data (username and `a_pub`) to the server and receive
@@ -25,7 +27,7 @@
//! can return error in case of malicious `b_pub`.
//!
//! ```ignore
-//! let private_key = srp6a_private_key::<Sha256>(username, password, salt);
+//! let private_key = srp_private_key::<Sha256>(username, password, salt);
//! let verifier = client.get_verifier(&private_key, &b_pub)?;
//! ```
//!
@@ -53,19 +55,20 @@
//! let pwd_verifier = SrpClient::<Sha256>::register(&private_key, &srp_params);
//! conn.send_registration_data(username, salt, pwd_verifier);
//! ```
+
+//let buf = rng.gen_iter::<u8>().take(l).collect::<Vec<u8>>();
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};
/// SRP client state before handshake with the server.
pub struct SrpClient<'a, D: Digest> {
- params: &'a SrpParams,
+ params: &'a SrpGroup,
a: BigUint,
a_pub: BigUint,
@@ -80,11 +83,10 @@ pub struct SrpClientVerifier<D: Digest> {
key: GenericArray<u8, D::OutputSize>,
}
-/// Compute user private key as described in the SRP6a. Consider using proper
+/// Compute user private key as described in the RFC 5054. Consider using proper
/// password hashing algorithm instead.
-pub fn srp6a_private_key<D: Digest>(username: &[u8], password: &[u8],
- salt: &[u8]
- ) -> GenericArray<u8, D::OutputSize>
+pub fn srp_private_key<D: Digest>(username: &[u8], password: &[u8], salt: &[u8])
+ -> GenericArray<u8, D::OutputSize>
{
let p = {
let mut d = D::new();
@@ -101,10 +103,8 @@ pub fn srp6a_private_key<D: Digest>(username: &[u8], password: &[u8],
impl<'a, D: Digest> SrpClient<'a, D> {
/// Create new SRP client instance.
- pub fn new<R: Rng>(params: &'a SrpParams, rng: &mut R) -> Self {
- let l = params.n.bits()/8;
- let buf = rng.gen_iter::<u8>().take(l).collect::<Vec<u8>>();
- let a = BigUint::from_bytes_le(&buf);
+ pub fn new(a: &[u8], params: &'a SrpGroup) -> Self {
+ let a = BigUint::from_bytes_be(a);
let a_pub = params.powm(&a);
Self { params, a, a_pub, d: Default::default() }
@@ -112,16 +112,17 @@ impl<'a, D: Digest> SrpClient<'a, D> {
/// Get password verfier for user registration on the server
pub fn get_password_verifier(&self, private_key: &[u8]) -> Vec<u8> {
- let x = BigUint::from_bytes_le(&private_key);
+ let x = BigUint::from_bytes_be(&private_key);
let v = self.params.powm(&x);
- v.to_bytes_le()
+ v.to_bytes_be()
}
fn calc_key(&self, b_pub: &BigUint, x: &BigUint, u: &BigUint)
-> GenericArray<u8, D::OutputSize>
{
let n = &self.params.n;
- let interm = (&self.params.k * self.params.powm(x)) % n;
+ let k = self.params.compute_k::<D>();
+ let interm = (k * self.params.powm(x)) % n;
// Because we do operation in modulo N we can get: (kv + g^b) < kv
let v = if b_pub > &interm {
(b_pub - &interm) % n
@@ -130,7 +131,7 @@ impl<'a, D: Digest> SrpClient<'a, D> {
};
// S = |B - kg^x| ^ (a + ux)
let s = powm(&v, &(&self.a + (u*x) % n ), n);
- D::digest(&s.to_bytes_le())
+ D::digest(&s.to_bytes_be())
}
/// Process server reply to the handshake.
@@ -139,25 +140,25 @@ impl<'a, D: Digest> SrpClient<'a, D> {
{
let u = {
let mut d = D::new();
- d.input(&self.a_pub.to_bytes_le());
+ d.input(&self.a_pub.to_bytes_be());
d.input(b_pub);
- BigUint::from_bytes_le(&d.result())
+ BigUint::from_bytes_be(&d.result())
};
- let b_pub = BigUint::from_bytes_le(b_pub);
+ let b_pub = BigUint::from_bytes_be(b_pub);
// Safeguard against malicious B
if &b_pub % &self.params.n == BigUint::zero() {
return Err(SrpAuthError{ description: "Malicious b_pub value" })
}
- let x = BigUint::from_bytes_le(&private_key);
+ let x = BigUint::from_bytes_be(&private_key);
let key = self.calc_key(&b_pub, &x, &u);
// M1 = H(A, B, K)
let proof = {
let mut d = D::new();
- d.input(&self.a_pub.to_bytes_le());
- d.input(&b_pub.to_bytes_le());
+ d.input(&self.a_pub.to_bytes_be());
+ d.input(&b_pub.to_bytes_be());
d.input(&key);
d.result()
};
@@ -165,7 +166,7 @@ impl<'a, D: Digest> SrpClient<'a, D> {
// M2 = H(A, M1, K)
let server_proof = {
let mut d = D::new();
- d.input(&self.a_pub.to_bytes_le());
+ d.input(&self.a_pub.to_bytes_be());
d.input(&proof);
d.input(&key);
d.result()
@@ -180,7 +181,7 @@ impl<'a, D: Digest> SrpClient<'a, D> {
/// Get public ephemeral value for handshaking with the server.
pub fn get_a_pub(&self) -> Vec<u8> {
- self.a_pub.to_bytes_le()
+ self.a_pub.to_bytes_be()
}
}