Skip to content

SRP-6a protocol implementation for .NET Standard 1.6+ and .NET Framework 3.5+

License

Notifications You must be signed in to change notification settings

secure-remote-password/srp.net

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

79 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Secure Remote Password for .NET

AppveyorCoverageTestsNuGet

A modern SRP-6a implementation for .NET Standard 1.6+ and .NET Framework 3.5+.
Based on and is compatible with secure-remote-password npm package by Linus Unnebäck (see Compatibility).

Installation

dotnet add package srp

Usage

Signing up

To create an account, a client provides the following three values:

  • Identifier (username or email)
  • Salt
  • Verifier

The salt and verifier are calculated as follows:

usingSecureRemotePassword;// a user enters his name and passwordvaruserName="alice";varpassword="password123";varclient=newSrpClient();varsalt=client.GenerateSalt();varprivateKey=client.DerivePrivateKey(salt,userName,password);varverifier=client.DeriveVerifier(privateKey);// send userName, salt and verifier to server

Logging in

Authentication involves several steps:

1. Client → Server: I, A

The client generates an ephemeral secret/public value pair and sends the public value and user name to server:

usingSecureRemotePassword;// a user enters his namevaruserName="alice";varclient=newSrpClient();varclientEphemeral=client.GenerateEphemeral(verifier);// send userName and clientEphemeral.Public to server

2. Server → Client: s, B

The server retrieves salt and verifier from the database using the client-provided userName. Then it generates its own ephemeral secret/public value pair:

usingSecureRemotePassword;// retrieved from the databasevarsalt="beb25379...";varverifier="7e273de8...";varserver=newSrpServer();varserverEphemeral=server.GenerateEphemeral();// store serverEphemeral.Secret for later use// send salt and serverEphemeral.Public to the client

3. Client → Server: M1

The client derives the shared session key and a proof of it to provide to the server:

usingSecureRemotePassword;// a user enters his passwordvarpassword="password123";varclient=newSrpClient();varprivateKey=client.DerivePrivateKey(salt,userName,password);varclientSession=client.DeriveSession(clientEphemeral.Secret,serverPublicEphemeral,salt,userName,privateKey);// send clientSession.Proof to the server

4. Server → Client: M2

The server derives the shared session key and verifies that the client has the same key using the provided proof value:

usingSecureRemotePassword;// get the serverEphemeral.Secret stored in step 2varserverSecretEphemeral="e487cb59...";varserver=newSrpServer();varserverSession=server.DeriveSession(serverSecretEphemeral,clientPublicEphemeral,salt,userName,verifier,clientSessionProof);// send serverSession.Proof to the client

5. Client verifies M2

Finally, the client verifies that the server has derived the same session key using the server's proof value:

usingSecureRemotePassword;varclient=newSrpClient();client.VerifySession(clientEphemeral.Public,clientSession,serverSessionProof);

Authentication at a glance

usingSecureRemotePassword;varclient=newSrpClient();varserver=newSrpServer();// sign upvarsalt=client.GenerateSalt();varprivateKey=client.DerivePrivateKey(salt,username,password);varverifier=client.DeriveVerifier(privateKey);// authenticatevarclientEphemeral=client.GenerateEphemeral();varserverEphemeral=server.GenerateEphemeral(verifier);varclientSession=client.DeriveSession(clientEphemeral.Secret,serverEphemeral.Public,salt,username,privateKey);varserverSession=server.DeriveSession(serverEphemeral.Secret,clientEphemeral.Public,salt,username,verifier,clientSession.Proof);client.VerifySession(clientEphemeral.Public,clientSession,serverSession.Proof);// both the client and the server have the same session keyAssert.AreEqual(clientSession.Key,serverSession.Key);

Custom protocol parameters

This SRP-6a implementation uses sha256 hash function and 2048-bit group values by default. Any class derived from HashAlgorithm can be used as H. Customizing the parameters is easy:

usingSystem.Security.Cryptography;usingSecureRemotePassword;// use predefined 4096-bit group with SHA512 hash functionvarcustomParams=SrpParameters.Create4096<SHA512>();

SrpParameters has helper methods for all predefined groups from RFC5054: Create1024<SHA1>(), etc.

It's also possible to specify custom values of N and g:

varN="D4C7F8A2B32C11B8FBA9581EC4BA...";varcustomParams=SrpParameters.Create<SHA1>(N,"02");

Custom SRP parameters are then passed to SrpClient and SrpServer constructors. Make sure to use the same parameters on both sides:

varclient=newSrpClient(customParams);varserver=newSrpServer(customParams);

Compatibility with other implementations

srp.net is designed to be compatible with other implementations hosted in secure-remote-password organization.

At the time of writing, the secure-remote-password npm package is incompatible with this implementation because it does not pad values according to RFC5054.

  • If you have control over both client and server, it is recommended to upgrade both to this version, as outlined here.
  • If you are forced to maintain compatibility with an existing server, you can disable padding by initializing the client with new SrpClient(new SrpParameters { PaddedLength = 0 }). This is not recommended, as the resulting behavior is incompatible with libraries that follow the standard.

Other compatible libraries are listed here.

References

close