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
or related.
§Usage
The usage example start on the server side. Client side interaction is marked explicit when needed.
§1. A new user, welcome Alice
use srp6::prelude::*;
// this is happening on the client,
// the password is never send to the server at any time
let new_username = Username::from("alice");
let user_password = ClearTextPassword::from("password123");
let (salt_s, verifier_v) = Srp6_4096::default()
.generate_new_user_secrets(
&new_username,
&user_password
);
assert_eq!(salt_s.num_bytes(), Srp6_4096::KEY_LEN);
assert_eq!(verifier_v.num_bytes(), Srp6_4096::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 Alice
On the server side (when alice is already registered)
- when a user/client connects they would send their
Username
first - with the username the server will lookup their
Salt
andPasswordVerifier
from a user database or pw file - the server starts the authentication process with a
Handshake
send to the client - the server keeps a
HandshakeProofVerifier
for the user in order to verify the proof he will get from the client later on
use srp6::prelude::*;
#[path = "doc_test_mocks.rs"]
mod mocks;
// the username is sent by the client
let user = mocks::lookup_user_details("alice");
// the server starts the handshake
let srp = Srp6_4096::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_4096::KEY_LEN);
// send `handshake` to the client
// keep `proof_verifier` for later in a session or cache
§3. A Proof
that Alice is Alice
- with the handshake, alice needs to create
Proof
that she is who she says she is - this
Proof
and herPublicKey
will be sent to the server where it is verified
use srp6::prelude::*;
#[path = "doc_test_mocks.rs"]
mod mocks;
// this is entered by the user on the client (none is sent to the server)
let username = "alice";
let password = "password123";
// this comes from the server
let handshake = mocks::handshake_from_the_server(username);
// the final proof calculation
let (proof, strong_proof_verifier) = handshake
.calculate_proof(username, password)
.unwrap();
// send this `proof` to the server
// `strong_proof_verifier` is kept for the final verification
§4. Verify Proof
from Alice
- The client sends the proof (
HandshakeProof
) to the server - The server calculates their 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)
use srp6::prelude::*;
#[path = "doc_test_mocks.rs"]
mod mocks;
// this comes from the server
let username = "alice";
let proof_verifier = mocks::stored_proof_verifier_from_step_2(username);
let proof_from_alice = mocks::alice_proof();
// the server verifies the proof from alice
let (strong_proof, session_key_server) = proof_verifier
.verify_proof(&proof_from_alice)
.expect("proof was invalid");
// `strong_proof` is sent back to alice
§5. Alice verifies the server
- The client receivs the strong proof (
StrongProof
K) from the server - Alice calculates their 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::prelude::*;
#[path = "doc_test_mocks.rs"]
mod mocks;
// see the previous step..
let strong_proof_verifier = mocks::strong_proof_verifier_from_step_3();
let strong_proof = mocks::strong_proof_from_the_server();
// alice verifies the proof from the server
strong_proof_verifier
.verify_strong_proof(&strong_proof)
.expect("strong proof was invalid");
§Note on key length
this crate provides some default keys preconfigured and aliased. The modulus prime and genrator numbers are taken from RFC5054.
§Note on hash length
The original RFC5054 uses SHA1 as the hash function. This crate uses SHA512 as the default hash function. Because SHA1 is considered weak, it is recommended to use newer versions of the SHA family. The hash length is 64 bytes for SHA512 instead of 20 bytes for SHA1. If you really need to use SHA1, you can use the dangerous
feature.
§Further details and domain vocabolary
- You can find the documentation of SRP6 variables in a dedicated module.
- RFC2945 that describes in detail the Secure remote password protocol (SRP).
- RFC5054 that describes SRP6 for TLS Authentication
- check out the 2 examples that illustrates the srp authentication flow as well
Re-exports§
pub use defaults::*;
Modules§
- defaults
- default prime modulus and generator numbers taken from RFC5054 Appendix A, so they can be treated as vetted and safe.
- hash
- prelude
- protocol_
details - A very brief summary of the papers and RFCs of SRP6 and SRP6a
- rfc_
5054_ appendix_ a - rfc_
lingo
Structs§
- Handshake
- Contains all variables needed for a successful session key generation provided by the server to the client
- Handshake
Proof - Contains the client’s
PublicKey
and theirProof
and is sent to the server - Handshake
Proof Verifier - This is responsible for verifying a
HandshakeProof
that is provided by the client to the server - Srp6
- Main interaction point for the server
- Strong
Proof Verifier - Verifies the
StrongProof
provided by the server to the client - User
Credentials Username
andClearTextPassword
used on the client side- User
Secrets - User details composes
Username
,Salt
andPasswordVerifier
in one struct
Traits§
- HostAPI
- this trait provides a higher level api
Functions§
- calculate_
k k = H(N | PAD(g))
(k = 3 for dangerous SRP-6)- calculate_
p_ hash - hashes the user and the password (used for client private key
x
) - calculate_
password_ verifier_ v - here we calculate the
PasswordVerifier
calledv
based onx
Note: something that only needs to be done on user pw change, or user creationx
: Private key (derived from p and s)v
: Password verifierg
: A generator modulo NN
: A large safe prime (N = 2q+1, where q is prime) formula:v = g^x % N
- calculate_
private_ key_ x x
is the users private key (only they know)- calculate_
proof_ M - calculate_
pubkey_ A - [
../rfc_lingo::A
] is thePublicKey
of the client formula:A = g^a % N
- calculate_
pubkey_ B - [
PublicKey
][../rfc_lingo::B
] is the hosts public keyB = kv + g^b
- calculate_
session_ key_ S_ for_ client - client version of the session key calculation, depends on
- calculate_
session_ key_ S_ for_ host - host version of a session key for a given user S: is the session key of a user u: is the hash of user and server pub keys
- calculate_
session_ key_ hash_ interleave_ K - the hash of a session key
S
that is calledK
S: is the session key of a user K: is the hash of S, just not that straight - calculate_
strong_ proof_ M2 - todo(verify): check if padding is needed or not
formula:
H(A | M | K)
- calculate_
u - [
../rfc_lingo::u
] is the hash of host’s [PublicKey
][../rfc_lingo::A
] and client’s [PublicKey
][../rfc_lingo::B
] formula:H(PAD(A) | PAD(B))
The Padding is based on the key length, e.g. if N is 1024 bit, the padding is 128 bytes - generate_
private_ key PrivateKey
a
orb
is in fact just a big (positive) random number- generate_
salt Salt
s
is a random number
Type Aliases§
- Clear
Text Password - Clear text password
p
asstr
- Clear
Text Password Ref - Generator
- Refers to the modulus generator
g
- KeyPair
- A pair of
PublicKey
B andPrivateKey
b - Multiplier
Parameter - Refers to a multiplier parameter
k
(k = H(N, g) in SRP-6a, k = 3 for dangerous SRP-6) - Password
Verifier - Password Verifier is the users secret on the server side
- Prime
Modulus - Refers to a large safe prime called
N
(N = 2q+1
, whereq
is prime) - Private
Key - Refers to a private secret random number a (user), b (server)
- Proof
- Refers to
M
andM1
Proof of server and client - Public
Key - Refers to a Public shared key called A (user), B (server)
- Result
- encapsulates a
crate::error::Srp6Error
- Salt
- Refers to a User’s salt called
s
- Session
Key - Refers to the SessionKey
S
- Strong
Proof - Refers to
M2
the hash of Proof - Strong
Session Key - Refers to the StrongSessionKey
K
- Username
- Username
I
asString
- Username
Ref - Username reference
I
as&str