<PackageReference Include="BouncyCastle.Cryptography" Version="2.5.1" />

Srp6Server

public class Srp6Server
using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.Math; using Org.BouncyCastle.Security; namespace Org.BouncyCastle.Crypto.Agreement.Srp { public class Srp6Server { protected BigInteger N; protected BigInteger g; protected BigInteger v; protected SecureRandom random; protected IDigest digest; protected BigInteger A; protected BigInteger privB; protected BigInteger pubB; protected BigInteger u; protected BigInteger S; protected BigInteger M1; protected BigInteger M2; protected BigInteger Key; public virtual void Init(BigInteger N, BigInteger g, BigInteger v, IDigest digest, SecureRandom random) { this.N = N; this.g = g; this.v = v; this.random = random; this.digest = digest; } public virtual void Init(Srp6GroupParameters group, BigInteger v, IDigest digest, SecureRandom random) { Init(group.N, group.G, v, digest, random); } public virtual BigInteger GenerateServerCredentials() { BigInteger bigInteger = Srp6Utilities.CalculateK(digest, N, g); privB = SelectPrivateValue(); pubB = bigInteger.Multiply(v).Mod(N).Add(g.ModPow(privB, N)) .Mod(N); return pubB; } public virtual BigInteger CalculateSecret(BigInteger clientA) { A = Srp6Utilities.ValidatePublicValue(N, clientA); u = Srp6Utilities.CalculateU(digest, N, A, pubB); S = CalculateS(); return S; } protected virtual BigInteger SelectPrivateValue() { return Srp6Utilities.GeneratePrivateValue(digest, N, g, random); } private BigInteger CalculateS() { return v.ModPow(u, N).Multiply(A).Mod(N) .ModPow(privB, N); } public virtual bool VerifyClientEvidenceMessage(BigInteger clientM1) { if (A == null || pubB == null || S == null) throw new CryptoException("Impossible to compute and verify M1: some data are missing from the previous operations (A,B,S)"); if (Srp6Utilities.CalculateM1(digest, N, A, pubB, S).Equals(clientM1)) { M1 = clientM1; return true; } return false; } public virtual BigInteger CalculateServerEvidenceMessage() { if (A == null || M1 == null || S == null) throw new CryptoException("Impossible to compute M2: some data are missing from the previous operations (A,M1,S)"); M2 = Srp6Utilities.CalculateM2(digest, N, A, M1, S); return M2; } public virtual BigInteger CalculateSessionKey() { if (S == null || M1 == null || M2 == null) throw new CryptoException("Impossible to compute Key: some data are missing from the previous operations (S,M1,M2)"); Key = Srp6Utilities.CalculateKey(digest, N, S); return Key; } } }