Srp.net Save

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

Project README

Secure Remote Password for .NET

Appveyor Coverage Tests NuGet

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:

using SecureRemotePassword;

// a user enters his name and password
var userName = "alice";
var password = "password123";

var client = new SrpClient();
var salt = client.GenerateSalt();
var privateKey = client.DerivePrivateKey(salt, userName, password);
var verifier = 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:

using SecureRemotePassword;

// a user enters his name
var userName = "alice";

var client = new SrpClient();
var clientEphemeral = 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:

using SecureRemotePassword;

// retrieved from the database
var salt = "beb25379...";
var verifier = "7e273de8...";

var server = new SrpServer();
var serverEphemeral = 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:

using SecureRemotePassword;

// a user enters his password
var password = "password123";

var client = new SrpClient();
var privateKey = client.DerivePrivateKey(salt, userName, password);
var clientSession = 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:

using SecureRemotePassword;

// get the serverEphemeral.Secret stored in step 2
var serverSecretEphemeral = "e487cb59...";

var server = new SrpServer();
var serverSession = 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:

using SecureRemotePassword;

var client = new SrpClient();
client.VerifySession(clientEphemeral.Public, clientSession, serverSessionProof);

Authentication at a glance

using SecureRemotePassword;

var client = new SrpClient();
var server = new SrpServer();

// sign up
var salt = client.GenerateSalt();
var privateKey = client.DerivePrivateKey(salt, username, password);
var verifier = client.DeriveVerifier(privateKey);

// authenticate
var clientEphemeral = client.GenerateEphemeral();
var serverEphemeral = server.GenerateEphemeral(verifier);
var clientSession = client.DeriveSession(clientEphemeral.Secret, serverEphemeral.Public, salt, username, privateKey);
var serverSession = 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 key
Assert.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:

using System.Security.Cryptography;
using SecureRemotePassword;

// use predefined 4096-bit group with SHA512 hash function
var customParams = 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:

var N = "D4C7F8A2B32C11B8FBA9581EC4BA...";
var customParams = 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:

var client = new SrpClient(customParams);
var server = new SrpServer(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

Open Source Agenda is not affiliated with "Srp.net" Project. README Source: secure-remote-password/srp.net

Open Source Agenda Badge

Open Source Agenda Rating