Crate srp6

source · []
Expand description

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

NOTE: Please do only use key length >= 2048 bit in production. You can do so by using Srp6_2048 or Srp6_4096.

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_2048::default().generate_new_user_secrets(
    new_username,
    user_password
);

assert_eq!(salt_s.num_bytes(), Srp6_2048::KEY_LEN);
assert_eq!(verifier_v.num_bytes(), Srp6_2048::KEY_LEN);

// 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_2048::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(), Srp6_2048::KEY_LEN);

// TODO: next step: the client calculates proof

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

4. Verify Proof from Bob

  • The client sends the proof ([HandshakeProof]) to the server
  • The server calculates his version of the Proof and compoares if they match
  • On Success both parties have calculated a strong proof (StrongProof M2) and a session key (StrongSessionKey K)
// this comes from the server
let username = "Bob";
let proof_verifier = mocked::stored_proof_verifier_from_step_2(username);
let proof_from_bob = mocked::bobs_proof();

let strong_proof = proof_verifier.verify_proof(&proof_from_bob);
assert!(strong_proof.is_ok());
let (strong_proof, session_key_server) = strong_proof.unwrap();

// `strong_proof` is sent back to bob

5. Bob verifies the host

  • The client receivs the strong proof (StrongProof K) from the server
  • Bob calculates his own strong proof and verifies the both match
  • On Success both parties have verified each other and have a shared strong proof (StrongProof M2) and a session key (StrongSessionKey K)
use srp6::*;

let strong_proof_verifier = mocked::strong_proof_verifier_from_step_3();
let strong_proof = mocked::strong_proof_from_step_4_from_the_server();

let res = strong_proof_verifier.verify_strong_proof(&strong_proof);
assert!(res.is_ok());

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