123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168 |
- #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 client 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 Srp6Client
- {
- protected BigInteger N;
- protected BigInteger g;
- protected BigInteger privA;
- protected BigInteger pubA;
- protected BigInteger B;
- protected BigInteger x;
- protected BigInteger u;
- protected BigInteger S;
- protected BigInteger M1;
- protected BigInteger M2;
- protected BigInteger Key;
- protected IDigest digest;
- protected SecureRandom random;
- public Srp6Client()
- {
- }
- /**
- * Initialises the client to begin new 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 digest The digest algorithm associated with the client's verifier
- * @param random For key generation
- */
- public virtual void Init(BigInteger N, BigInteger g, IDigest digest, SecureRandom random)
- {
- this.N = N;
- this.g = g;
- this.digest = digest;
- this.random = random;
- }
- public virtual void Init(Srp6GroupParameters group, IDigest digest, SecureRandom random)
- {
- Init(group.N, group.G, digest, random);
- }
- /**
- * Generates client's credentials given the client's salt, identity and password
- * @param salt The salt used in the client's verifier.
- * @param identity The user's identity (eg. username)
- * @param password The user's password
- * @return Client's public value to send to server
- */
- public virtual BigInteger GenerateClientCredentials(byte[] salt, byte[] identity, byte[] password)
- {
- this.x = Srp6Utilities.CalculateX(digest, N, salt, identity, password);
- this.privA = SelectPrivateValue();
- this.pubA = g.ModPow(privA, N);
- return pubA;
- }
- /**
- * Generates client's verification message given the server's credentials
- * @param serverB The server's credentials
- * @return Client's verification message for the server
- * @throws CryptoException If server's credentials are invalid
- */
- public virtual BigInteger CalculateSecret(BigInteger serverB)
- {
- this.B = Srp6Utilities.ValidatePublicValue(N, serverB);
- this.u = Srp6Utilities.CalculateU(digest, N, pubA, B);
- this.S = CalculateS();
- return S;
- }
- protected virtual BigInteger SelectPrivateValue()
- {
- return Srp6Utilities.GeneratePrivateValue(digest, N, g, random);
- }
- private BigInteger CalculateS()
- {
- BigInteger k = Srp6Utilities.CalculateK(digest, N, g);
- BigInteger exp = u.Multiply(x).Add(privA);
- BigInteger tmp = g.ModPow(x, N).Multiply(k).Mod(N);
- return B.Subtract(tmp).Mod(N).ModPow(exp, N);
- }
-
- /**
- * Computes the client evidence message M1 using the previously received values.
- * To be called after calculating the secret S.
- * @return M1: the client side generated evidence message
- * @throws CryptoException
- */
- public virtual BigInteger CalculateClientEvidenceMessage()
- {
- // Verify pre-requirements
- if (this.pubA == null || this.B == null || this.S == null)
- {
- throw new CryptoException("Impossible to compute M1: " +
- "some data are missing from the previous operations (A,B,S)");
- }
- // compute the client evidence message 'M1'
- this.M1 = Srp6Utilities.CalculateM1(digest, N, pubA, B, S);
- return M1;
- }
- /** Authenticates the server evidence message M2 received and saves it only if correct.
- * @param M2: the server side generated evidence message
- * @return A boolean indicating if the server message M2 was the expected one.
- * @throws CryptoException
- */
- public virtual bool VerifyServerEvidenceMessage(BigInteger serverM2)
- {
- // Verify pre-requirements
- if (this.pubA == null || this.M1 == null || this.S == null)
- {
- throw new CryptoException("Impossible to compute and verify M2: " +
- "some data are missing from the previous operations (A,M1,S)");
- }
- // Compute the own server evidence message 'M2'
- BigInteger computedM2 = Srp6Utilities.CalculateM2(digest, N, pubA, M1, S);
- if (computedM2.Equals(serverM2))
- {
- this.M2 = serverM2;
- return true;
- }
- return false;
- }
- /**
- * Computes the final session key as a result of the SRP successful mutual authentication
- * To be called after verifying the server evidence message M2.
- * @return Key: the mutually authenticated symmetric session key
- * @throws CryptoException
- */
- public virtual BigInteger CalculateSessionKey()
- {
- // Verify pre-requirements (here we enforce a previous calculation of M1 and M2)
- 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
|