Crate srp6[][src]

Expand description

An implementation of Secure Remote Password (SRP6) authentication protocol.

Usage

The usage example start on the server side. Client side interaction is marked explicit when needed.

1. A new user, welcome Bob

use srp6::*;

// this is happening on the client, the password is never send
// to the server at any time
let new_username: UsernameRef = "Bob";
let user_password: &ClearTextPassword = "secret-password";

let (salt_s, verifier_v) = Srp6_256::default().generate_new_user_secrets(
    new_username,
    user_password
);

assert_eq!(salt_s.num_bytes(), 256 / 8);
assert_eq!(verifier_v.num_bytes(), 256 / 8);

// The server needs to persist,
// `new_username`, `salt_s` and `verifier_v` in a user database / pw file

NOTE: the password of the user will not be stored!

NOTE2: the salt and verifier will never be the same, they have a random component to it

2. A session handshake for Bob

On the server side

  • when a user/client connects they would send their Username first
  • with the username the server will lookup their Salt and PasswordVerifier from a user database or pw file
  • with this data the server would start the authentication with a Handshake send to the client
  • the server would also keep a HandshakeProofVerifier for this user in order to verify the proof he will get from the client
use srp6::*;

// the username is sent by the client
let user = mocked::lookup_user_details("Bob");

let srp = Srp6_256::default();
let (handshake, proof_verifier) = srp.start_handshake(&user);
assert_eq!(handshake.s, user.salt);
assert_eq!(handshake.N, srp.N);
assert_eq!(handshake.g, srp.g);
assert_eq!(handshake.B.num_bytes(), 256 / 8);

// TODO: next step: the client calculates proof

mod mocked {
    use srp6::*;

    /// this is a mock
    /// normally this would come from a user database
    pub fn lookup_user_details(username: UsernameRef) -> UserDetails {
        use std::convert::TryInto;

        UserDetails {
            username: username.to_owned(),
            salt: "C7005DA4B7FA6F1B1C75946A74BCDBA48322866E648BB69BA904337993C69591"
                .try_into()
                .unwrap(),
            verifier: "4B0F2ACB3E6023EFE3088DB8F1EAE0C6972622400E4A0406C577C14080E58CBF"
                .try_into()
                .unwrap(),
        }
    }
}

3. A Proof that Bob is Bob

  • with the handshake, Bob needs to create Proof that he is Bob
  • this Proof and his PublicKey will be sent to the server where it is verified
use srp6::*;

// this is entered by the user
let username = "Bob";
let bobs_password: &ClearTextPassword = "secret-password";

// this comes from the server
let handshake = mocked::handshake_from_the_server(username);

// the final proof calculation
let (proof, strong_proof_verifier) = handshake
    .calculate_proof(username, bobs_password)
    .unwrap();

// `proof` send this proof to the server
// `strong_proof_verifier` is kept for the final verification

mod mocked {
    use srp6::*;

    /// this is a mock, nothing you should do on the client side
    pub fn handshake_from_the_server(username: UsernameRef) -> Handshake<32, 32> {
        let user = lookup_user_details(username);
        let (handshake, _) = Srp6_256::default().start_handshake(&user);
        handshake
    }

    /// this is a mock
    /// normally this would come from a user database
    pub fn lookup_user_details(username: UsernameRef) -> UserDetails {
        use std::convert::TryInto;

        UserDetails {
            username: username.to_owned(),
            salt: "C7005DA4B7FA6F1B1C75946A74BCDBA48322866E648BB69BA904337993C69591"
                .try_into()
                .unwrap(),
            verifier: "4B0F2ACB3E6023EFE3088DB8F1EAE0C6972622400E4A0406C577C14080E58CBF"
                .try_into()
                .unwrap(),
        }
    }
}

4. Verify Proof from Bob

  • The client sends the proof to the server
  • The server calculates his version of the Proof and compoares if they match

// this comes from the server
let username = "Bob";
let handshake = mocked::stored_proof_verifier_from_step_2(username);

mod mocked {
    use srp6::*;

    /// this is a mock, nothing you should do on the client side
    pub fn stored_proof_verifier_from_step_2(username: UsernameRef) -> HandshakeProofVerifier {
        let user = lookup_user_details(username);
        let (_, proof_verifier) = Srp6_256::default().start_handshake(&user);
        proof_verifier
    }

    /// this is a mock
    /// normally this would come from a user database
    pub fn lookup_user_details(username: UsernameRef) -> UserDetails {
        use std::convert::TryInto;

        UserDetails {
            username: username.to_owned(),
            salt: "C7005DA4B7FA6F1B1C75946A74BCDBA48322866E648BB69BA904337993C69591"
                .try_into()
                .unwrap(),
            verifier: "4B0F2ACB3E6023EFE3088DB8F1EAE0C6972622400E4A0406C577C14080E58CBF"
                .try_into()
                .unwrap(),
        }
    }
}

Note on key length

this crate provides some default keys preconfigured and aliased. The modulus prime and genrator numbers are taken from RFC5054.

Further details and domain vocabolary

Re-exports

pub use defaults::*;

Modules

default prime modulus and generator numbers taken from RFC5054 Appendix A, so they can be treated as vetted and safe.

A very brief summary of the papers and RFCs of SRP6 and SRP6a

Structs

Contains all variables needed for a successful session key generation provided by the server to the client

Contains the client’s PublicKey and their Proof and is sent to the server

This is responsible for verifying a HandshakeProof that is provided by the client to the server

Main interaction point for the server

Verifies the StrongProof provided by the server to the client

Username and ClearTextPassword used on the client side

User details composes Username, Salt and PasswordVerifier in one struct

Enums

Traits

this trait provides a higher level api

An attempted conversion that consumes self, which may or may not be expensive.

Type Definitions

Clear text password p as str

Refers to the modulus generator g

Refers to a multiplier parameter k (k = H(N, g) in SRP-6a, k = 3 for legacy SRP-6)

Password Verifier is the users secret on the server side

Refers to a large safe prime called N (N = 2q+1, where q is prime)

Refers to a private secret random number a (user), b (server)

Refers to M and M1 Proof of server and client

Refers to a Public shared key called A (user), B (server)

encapsulates a Srp6Error

Refers to a User’s salt called s

Refers to the SessionKey S

Refers to M2 the hash of Proof

Refers to the StrongSessionKey K

Username I as String

Username reference I as &str