You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
168 lines
5.5 KiB
168 lines
5.5 KiB
1 year ago
|
#if !BESTHTTP_DISABLE_ALTERNATE_SSL && (!UNITY_WEBGL || UNITY_EDITOR)
|
||
|
#pragma warning disable
|
||
|
using System;
|
||
|
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Parameters;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Math;
|
||
|
using BestHTTP.SecureProtocol.Org.BouncyCastle.Security;
|
||
|
|
||
|
namespace BestHTTP.SecureProtocol.Org.BouncyCastle.Crypto.Agreement.Srp
|
||
|
{
|
||
|
/**
|
||
|
* Implements the server side SRP-6a protocol. Note that this class is stateful, and therefore NOT threadsafe.
|
||
|
* This implementation of SRP is based on the optimized message sequence put forth by Thomas Wu in the paper
|
||
|
* "SRP-6: Improvements and Refinements to the Secure Remote Password Protocol, 2002"
|
||
|
*/
|
||
|
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 Srp6Server()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Initialises the server to accept a new client authentication attempt
|
||
|
* @param N The safe prime associated with the client's verifier
|
||
|
* @param g The group parameter associated with the client's verifier
|
||
|
* @param v The client's verifier
|
||
|
* @param digest The digest algorithm associated with the client's verifier
|
||
|
* @param random For key generation
|
||
|
*/
|
||
|
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);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Generates the server's credentials that are to be sent to the client.
|
||
|
* @return The server's public value to the client
|
||
|
*/
|
||
|
public virtual BigInteger GenerateServerCredentials()
|
||
|
{
|
||
|
BigInteger k = Srp6Utilities.CalculateK(digest, N, g);
|
||
|
this.privB = SelectPrivateValue();
|
||
|
this.pubB = k.Multiply(v).Mod(N).Add(g.ModPow(privB, N)).Mod(N);
|
||
|
|
||
|
return pubB;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Processes the client's credentials. If valid the shared secret is generated and returned.
|
||
|
* @param clientA The client's credentials
|
||
|
* @return A shared secret BigInteger
|
||
|
* @throws CryptoException If client's credentials are invalid
|
||
|
*/
|
||
|
public virtual BigInteger CalculateSecret(BigInteger clientA)
|
||
|
{
|
||
|
this.A = Srp6Utilities.ValidatePublicValue(N, clientA);
|
||
|
this.u = Srp6Utilities.CalculateU(digest, N, A, pubB);
|
||
|
this.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);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Authenticates the received client evidence message M1 and saves it only if correct.
|
||
|
* To be called after calculating the secret S.
|
||
|
* @param M1: the client side generated evidence message
|
||
|
* @return A boolean indicating if the client message M1 was the expected one.
|
||
|
* @throws CryptoException
|
||
|
*/
|
||
|
public virtual bool VerifyClientEvidenceMessage(BigInteger clientM1)
|
||
|
{
|
||
|
// Verify pre-requirements
|
||
|
if (this.A == null || this.pubB == null || this.S == null)
|
||
|
{
|
||
|
throw new CryptoException("Impossible to compute and verify M1: " +
|
||
|
"some data are missing from the previous operations (A,B,S)");
|
||
|
}
|
||
|
|
||
|
// Compute the own client evidence message 'M1'
|
||
|
BigInteger computedM1 = Srp6Utilities.CalculateM1(digest, N, A, pubB, S);
|
||
|
if (computedM1.Equals(clientM1))
|
||
|
{
|
||
|
this.M1 = clientM1;
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Computes the server evidence message M2 using the previously verified values.
|
||
|
* To be called after successfully verifying the client evidence message M1.
|
||
|
* @return M2: the server side generated evidence message
|
||
|
* @throws CryptoException
|
||
|
*/
|
||
|
public virtual BigInteger CalculateServerEvidenceMessage()
|
||
|
{
|
||
|
// Verify pre-requirements
|
||
|
if (this.A == null || this.M1 == null || this.S == null)
|
||
|
{
|
||
|
throw new CryptoException("Impossible to compute M2: " +
|
||
|
"some data are missing from the previous operations (A,M1,S)");
|
||
|
}
|
||
|
|
||
|
// Compute the server evidence message 'M2'
|
||
|
this.M2 = Srp6Utilities.CalculateM2(digest, N, A, M1, S);
|
||
|
return M2;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Computes the final session key as a result of the SRP successful mutual authentication
|
||
|
* To be called after calculating the server evidence message M2.
|
||
|
* @return Key: the mutual authenticated symmetric session key
|
||
|
* @throws CryptoException
|
||
|
*/
|
||
|
public virtual BigInteger CalculateSessionKey()
|
||
|
{
|
||
|
// Verify pre-requirements
|
||
|
if (this.S == null || this.M1 == null || this.M2 == null)
|
||
|
{
|
||
|
throw new CryptoException("Impossible to compute Key: " +
|
||
|
"some data are missing from the previous operations (S,M1,M2)");
|
||
|
}
|
||
|
this.Key = Srp6Utilities.CalculateKey(digest, N, S);
|
||
|
return Key;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
#pragma warning restore
|
||
|
#endif
|