项目作者: secure-remote-password

项目描述 :
SRP-6a protocol implementation for .NET Standard 1.6+ and .NET Framework 3.5+
高级语言: C#
项目地址: git://github.com/secure-remote-password/srp.net.git
创建时间: 2018-05-25T14:19:16Z
项目社区:https://github.com/secure-remote-password/srp.net

开源协议:MIT License

下载


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

  1. 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:

  1. using SecureRemotePassword;
  2. // a user enters his name and password
  3. var userName = "alice";
  4. var password = "password123";
  5. var client = new SrpClient();
  6. var salt = client.GenerateSalt();
  7. var privateKey = client.DerivePrivateKey(salt, userName, password);
  8. var verifier = client.DeriveVerifier(privateKey);
  9. // 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:

  1. using SecureRemotePassword;
  2. // a user enters his name
  3. var userName = "alice";
  4. var client = new SrpClient();
  5. var clientEphemeral = client.GenerateEphemeral(verifier);
  6. // 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:

  1. using SecureRemotePassword;
  2. // retrieved from the database
  3. var salt = "beb25379...";
  4. var verifier = "7e273de8...";
  5. var server = new SrpServer();
  6. var serverEphemeral = server.GenerateEphemeral();
  7. // store serverEphemeral.Secret for later use
  8. // 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:

  1. using SecureRemotePassword;
  2. // a user enters his password
  3. var password = "password123";
  4. var client = new SrpClient();
  5. var privateKey = client.DerivePrivateKey(salt, userName, password);
  6. var clientSession = client.DeriveSession(clientEphemeral.Secret,
  7. serverPublicEphemeral, salt, userName, privateKey);
  8. // 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:

  1. using SecureRemotePassword;
  2. // get the serverEphemeral.Secret stored in step 2
  3. var serverSecretEphemeral = "e487cb59...";
  4. var server = new SrpServer();
  5. var serverSession = server.DeriveSession(serverSecretEphemeral,
  6. clientPublicEphemeral, salt, userName, verifier, clientSessionProof);
  7. // 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:

  1. using SecureRemotePassword;
  2. var client = new SrpClient();
  3. client.VerifySession(clientEphemeral.Public, clientSession, serverSessionProof);

Authentication at a glance

  1. using SecureRemotePassword;
  2. var client = new SrpClient();
  3. var server = new SrpServer();
  4. // sign up
  5. var salt = client.GenerateSalt();
  6. var privateKey = client.DerivePrivateKey(salt, username, password);
  7. var verifier = client.DeriveVerifier(privateKey);
  8. // authenticate
  9. var clientEphemeral = client.GenerateEphemeral();
  10. var serverEphemeral = server.GenerateEphemeral(verifier);
  11. var clientSession = client.DeriveSession(clientEphemeral.Secret, serverEphemeral.Public, salt, username, privateKey);
  12. var serverSession = server.DeriveSession(serverEphemeral.Secret, clientEphemeral.Public, salt, username, verifier, clientSession.Proof);
  13. client.VerifySession(clientEphemeral.Public, clientSession, serverSession.Proof);
  14. // both the client and the server have the same session key
  15. 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:

  1. using System.Security.Cryptography;
  2. using SecureRemotePassword;
  3. // use predefined 4096-bit group with SHA512 hash function
  4. 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:

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

  1. var client = new SrpClient(customParams);
  2. 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