Library of SRP Functions used in SRP protocol. Refs: http://srp.stanford.edu/design.html http://www.ietf.org/internet-drafts/draft-ietf-tls-srp-09.txt Required Credit to Tom Wu for the SRP algo: "This product uses the 'Secure Remote Password' cryptographic authentication system developed by Tom Wu ([email protected])." Note: Method naming follows the SRP6 naming of variables which may be a single upper case or lower case character. This allows a reader to more easily follow the protocol at the expense of non-standard method naming convension.
Exemple #1
0
        /// <summary>
        /// Initiates the SRPP Request
        /// </summary>
        /// <param name="username">Username to login with</param>
        /// <param name="password">Password to login with</param>
        /// <param name="otherdata">Other data passed to LogonManager</param>
        /// <returns></returns>
        internal NetSRP.Request GenerateSRPRequest(String username, String password, Byte[] otherdata)
        {
            if ((this.HandshakeState != Handshake.State.NotInitialized) && (Handshake.State.AllowRequest & this.HandshakeState) != this.HandshakeState)
            {
                return(_request); // Already Created
            }
            if (username == null || password == null)
            {
                throw new NetSRP.HandShakeException("Need username and password to created SRP.Request");
            }

            // Set state and timer
            this.HandshakeState   = Handshake.State.Requesting;
            _cache.ExpirationTime = DateTime.Now.AddSeconds(Handshake.ExpirationInSeconds);

            // First get the public key A from random private a
            _cache.a = NetSRP.Geta();
            _cache.A = NetSRP.CalcA(N, g, _cache.a);

            // Save the password to use when the response comes in
            _cache.UserData = password;

            // Create a new request
            _request = new NetSRP.Request(username, _cache.A, otherdata);

            return(_request);
        }
Exemple #2
0
        /// <summary>
        /// Actually verifies received verification data (initiated remotely) + generates response
        /// </summary>
        /// <param name="verification"></param>
        private NetSRP.Verification VerificationOfActiveParty(NetSRP.Verification verification)
        {
            if ((Handshake.State.AllowVerificating & this.HandshakeState) != this.HandshakeState)
            {
                return(_verification); // double
            }
            // Set State
            this.HandshakeState = Handshake.State.Verificating;

            // Hello I am the one that is being connected to. So let's generate
            // the value M I should have in the SRPPackedData Object.
            Byte[] M = NetSRP.CalcM(N, g, _request.Username, _response.Salt, _request.A, _cache.B, _cache.K);

            // Compare
            if (!NetUtility.ArraysEqual(M, verification.M))
            {
                this.HandshakeState = Handshake.State.Denied | State.Failed;
                throw new NetSRP.HandShakeException("Invalid proof of Key. Username or password invalid.", new InvalidOperationException("Generated M does not match received M"));
            }

            // Ok, so their verification passed. Now let's proof that mine will to.
            _verification = new NetSRP.Verification(NetSRP.CalcM2(_request.A, verification.M, _cache.K));

            // Check expiration (maybe use timer?)
            if (_cache.ExpirationTime.CompareTo(DateTime.Now) < 0)
            {
                this.HandshakeState = Handshake.State.Expired;
                throw new NetSRP.HandShakeException("Hand was not shaken before it expired.");
            }

            return(_verification);
        }
Exemple #3
0
        /// <summary>
        /// Actually verifies received verification data (initiated locally)
        /// </summary>
        /// <param name="verification"></param>
        private Boolean VerificationOfPassiveParty(NetSRP.Verification verification)
        {
            if ((Handshake.State.AllowVerification & this.HandshakeState) != this.HandshakeState)
            {
                return(false);
            }

            // Hello I am the one that tries to connect. So let's generate the
            // value M2 I should have in the SRPPackedData Object.
            Byte[] M2 = NetSRP.CalcM2(_cache.A, _verification.M, _cache.K);

            // Compare
            if (!NetUtility.ArraysEqual(M2, verification.M2))
            {
                this.HandshakeState = Handshake.State.Failed;
                throw new NetSRP.HandShakeException("Username or password invalid.", new ArgumentException("Generated M2 does not match received M2"));
            }

            // Check expiration
            if (_cache.ExpirationTime.CompareTo(DateTime.Now) < 0)
            {
                this.HandshakeState = Handshake.State.Expired;
                throw new NetSRP.HandShakeException("Hand was not shaken before it expired.");
            }

            return(true);
        }
        /// <summary>
        /// Generates Salt and Verifier for username and password
        /// </summary>
        /// <param name="username"></param>
        /// <param name="password"></param>
        /// <param name="keysize"></param>
        /// <param name="salt"></param>
        /// <returns></returns>
        public static NetBigInteger PasswordVerifier(String username, String password, Int32 keysize, out Byte[] salt)
        {
            salt = NetSRP.GenerateSalt();
            NetBigInteger g, N = NetSRP.GetNandG(keysize, out g);

            return(NetSRP.PasswordVerifier(username, password, salt, N, g));
        }
Exemple #5
0
        /// <summary>
        /// Create a response on received request.
        /// </summary>
        /// <param name="request">Receieved Request</param>
        /// <returns></returns>
        private NetSRP.Response ResponseFromRequest(NetSRP.Request request)
        {
            if (Handshake._defaultLogonManager == null)
            {
                throw new NetSRP.HandShakeException("No HandShake.Passive functions are available until LogonManager is provided.");
            }

            if (this.HandshakeState != Handshake.State.NotInitialized && (Handshake.State.AllowResponse & this.HandshakeState) != this.HandshakeState)
            {
                return(_response);
            }

            // Set State and start timer
            this.HandshakeState   = Handshake.State.Responding;
            _cache.ExpirationTime = DateTime.Now.AddSeconds(Handshake.ExpirationInSeconds);

            if (request.A.Mod(N).IntValue == 0)
            {
                this.HandshakeState = Handshake.State.Failed;
                throw new NetSRP.HandShakeException("Request contains invalid data", new ArgumentException("A mod N is zero."));
            }

            Byte[]        salt;
            NetBigInteger v;

            // Get verifier
            try
            {
                v = Lookup(request, out salt);
            }
            catch (Exception exception)
            {
                this.HandshakeState = Handshake.State.Failed;
                throw new NetSRP.HandShakeException("LogonManager failed lookup.", exception);
            }

            if (v == null)
            {
                this.HandshakeState = Handshake.State.Denied;
                throw new NetSRP.HandShakeException("Wrong username or password."); // Clearly its username.
            }

            // Cache request
            _request        = request;
            _cache.UserData = _request.Username;

            // Get public ket B from random private b
            _cache.b = NetSRP.Getb();
            _cache.B = NetSRP.CalcB(N, g, _cache.b, v);

            // Create the response message
            _response = new NetSRP.Response(salt, _cache.B);

            // First create the key
            KeyFromRequest(request.A, v);

            return(_response);
        }
Exemple #6
0
        /// <summary>
        /// Generates key from request
        /// </summary>
        /// <param name="A">Generated A from request</param>
        /// <param name="v">Verifier v</param>
        private void KeyFromRequest(NetBigInteger A, NetBigInteger v)
        {
            // Shared random scrambler
            Lidgren.Network.NetBigInteger u = NetSRP.Calcu(A, _cache.B);

            // Sessionkey
            _cache.S = NetSRP.CalcSServer(N, A, v, u, _cache.b);
            _cache.K = NetSRP.CalcK(_cache.S);
        }
Exemple #7
0
        /// <summary>
        /// Generates Session key from response
        /// </summary>
        /// <param name="response"></param>
        /// <response></response>
        private NetSRP.Verification KeyFromResponse(NetSRP.Response response)
        {
            if ((Handshake.State.AllowVerificating & this.HandshakeState) != this.HandshakeState)
            {
                return(_verification); // Double Request
            }
            // When we get the response, get their public key B
            if (response.B.Mod(N).IntValue == 0)
            {
                this.HandshakeState = Handshake.State.Failed;
                throw new NetSRP.HandShakeException("Response contains invalid data", new ArgumentException("B mod N is zero."));
            }

            // Shared random scrambler
            NetBigInteger u = NetSRP.Calcu(_cache.A, response.B);

            if (u.IntValue == 0)
            {
                this.HandshakeState = Handshake.State.Failed;
                throw new NetSRP.HandShakeException("Response contains invalid data", new ArgumentException("u is zero."));
            }

            // Private key x
            NetBigInteger x = NetSRP.Calcx(response.Salt, _request.Username, _cache.UserData);

            // Cache Response;
            _response = response;

            // Session key
            _cache.S = NetSRP.CalcSClient(N, g, response.B, k, x, _cache.a, u);
            _cache.K = NetSRP.CalcK(_cache.S);


            // Create the verification
            _verification = new NetSRP.Verification(NetSRP.CalcM(N, g, _request.Username, response.Salt, _cache.A, response.B, _cache.K));

            // Set State
            this.HandshakeState = Handshake.State.Verificating;
            return(_verification);
        }
        /// <summary>
        /// Creates a new Handshake
        /// </summary>
        /// <param name="active">Is active party</param>
        /// <param name="keySize">keysize</param>
        /// <param name="logonManager">logonManager (only needed if passive)</param>
        internal Handshake(Boolean active, Int32 keySize, ILogonManager logonManager)
        {
            // Local Data setup
            _cache        = new NetSRP.State();
            _keySize      = keySize;
            _logonManager = logonManager ?? _defaultLogonManager;

            if (!active && _defaultLogonManager == null)
            {
                _defaultLogonManager = logonManager;
            }

            // We calculate N and G for this insance. I choose to do so, so you can
            // have different keysizes throughout your program and are not stuck with one
            N = NetSRP.GetNandG(_keySize, out g);
            k = NetSRP.Calck(N, g);

            // Set as NotInitialized
            this.HandshakeState = Handshake.State.NotInitialized;

            if (!active && _logonManager == null)
            {
                throw new InvalidOperationException("Receiving handshakes need a logonManager");
            }

            if (keySize == 0 || N == null || g == null || k == null)
            {
                throw new InvalidOperationException("Handshake not intialized");
            }

            // NOTE: this is caused by the length of the hailmessage - larger then 4096 goes over the MTU
            if (keySize < 1024 || keySize > 4096)
            {
                throw new NetException("SRP6Keysize is not supported by Lidgren.Network",
                                       new ArgumentOutOfRangeException("keySize"));
            }
        }
 /// <summary>
 /// Returns Verifier and Salt for request
 /// </summary>
 /// <param name="request">Request data</param>
 /// <param name="salt">salt output</param>
 /// <returns>verifier</returns>
 private NetBigInteger Lookup(NetSRP.Request request, out Byte[] salt)
 {
     return _logonManager.Lookup(request.Username, request.OtherData, out salt);
 }
Exemple #10
0
        /// <summary>
        /// Host stores v (password verifier) in database.
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <param name="salt"></param>
        /// <param name="N"></param>
        /// <param name="g"></param>
        /// <returns></returns>
        public static NetBigInteger PasswordVerifier(String userName, String password, Byte[] salt, NetBigInteger N, NetBigInteger g)
        {
            NetBigInteger x = NetSRP.Calcx(salt, userName, password);

            return(NetSRP.CalcV(N, g, x));
        }
        /// <summary>
        /// Actually verifies received verification data (initiated locally)
        /// </summary>
        /// <param name="verification"></param>
        private Boolean VerificationOfPassiveParty(NetSRP.Verification verification)
        {
            if ((Handshake.State.AllowVerification & this.HandshakeState) != this.HandshakeState)
                return false;

            // Hello I am the one that tries to connect. So let's generate the
            // value M2 I should have in the SRPPackedData Object.
            Byte[] M2 = NetSRP.CalcM2(_cache.A, _verification.M, _cache.K);

            // Compare
            if (!NetUtility.ArraysEqual(M2, verification.M2))
            {
                this.HandshakeState = Handshake.State.Failed;
                throw new NetSRP.HandShakeException("Username or password invalid.", new ArgumentException("Generated M2 does not match received M2"));
            }

            // Check expiration
            if (_cache.ExpirationTime.CompareTo(DateTime.Now) < 0)
            {
                this.HandshakeState = Handshake.State.Expired;
                throw new NetSRP.HandShakeException("Hand was not shaken before it expired.");
            }

            return true;
        }
        /// <summary>
        /// Generates Session key from response
        /// </summary>
        /// <param name="response"></param>
        /// <response></response>
        private NetSRP.Verification KeyFromResponse(NetSRP.Response response)
        {
            if ((Handshake.State.AllowVerificating & this.HandshakeState) != this.HandshakeState)
                return _verification; // Double Request

            // When we get the response, get their public key B
            if (response.B.Mod(N).IntValue == 0)
            {
                this.HandshakeState = Handshake.State.Failed;
                throw new NetSRP.HandShakeException("Response contains invalid data", new ArgumentException("B mod N is zero."));
            }

            // Shared random scrambler
            NetBigInteger u = NetSRP.Calcu(_cache.A, response.B);
            if (u.IntValue == 0)
            {
                this.HandshakeState = Handshake.State.Failed;
                throw new NetSRP.HandShakeException("Response contains invalid data", new ArgumentException("u is zero."));
            }

            // Private key x
            NetBigInteger x = NetSRP.Calcx(response.Salt, _request.Username, _cache.UserData);

            // Cache Response;
            _response = response;

            // Session key
            _cache.S = NetSRP.CalcSClient(N, g, response.B, k, x, _cache.a, u);
            _cache.K = NetSRP.CalcK(_cache.S);

            // Create the verification
            _verification = new NetSRP.Verification(NetSRP.CalcM(N, g, _request.Username, response.Salt, _cache.A, response.B, _cache.K));

            // Set State
            this.HandshakeState = Handshake.State.Verificating;
            return _verification;
        }
        /// <summary>
        /// Create a response on received request.
        /// </summary>
        /// <param name="request">Receieved Request</param>
        /// <returns></returns>
        private NetSRP.Response ResponseFromRequest(NetSRP.Request request)
        {
            if (Handshake._defaultLogonManager == null)
                throw new NetSRP.HandShakeException("No HandShake.Passive functions are available until LogonManager is provided.");

            if (this.HandshakeState != Handshake.State.NotInitialized && (Handshake.State.AllowResponse & this.HandshakeState) != this.HandshakeState)
                return _response;

            // Set State and start timer
            this.HandshakeState = Handshake.State.Responding;
            _cache.ExpirationTime = DateTime.Now.AddSeconds(Handshake.ExpirationInSeconds);

            if (request.A.Mod(N).IntValue == 0)
            {
                this.HandshakeState = Handshake.State.Failed;
                throw new NetSRP.HandShakeException("Request contains invalid data", new ArgumentException("A mod N is zero."));
            }

            Byte[] salt;
            NetBigInteger v;

            // Get verifier
            try
            {
                v = Lookup(request, out salt);
            }
            catch (Exception exception)
            {
                this.HandshakeState = Handshake.State.Failed;
                throw new NetSRP.HandShakeException("LogonManager failed lookup.", exception);
            }

            if (v == null)
            {
                this.HandshakeState = Handshake.State.Denied;
                throw new NetSRP.HandShakeException("Wrong username or password."); // Clearly its username.
            }

            // Cache request
            _request = request;
            _cache.UserData = _request.Username;

            // Get public ket B from random private b
            _cache.b = NetSRP.Getb();
            _cache.B = NetSRP.CalcB(N, g, _cache.b, v);

            // Create the response message
            _response = new NetSRP.Response(salt, _cache.B);

            // First create the key
            KeyFromRequest(request.A, v);

            return _response;
        }
        /// <summary>
        /// Actually verifies received verification data (initiated remotely) + generates response
        /// </summary>
        /// <param name="verification"></param>
        private NetSRP.Verification VerificationOfActiveParty(NetSRP.Verification verification)
        {
            if ((Handshake.State.AllowVerificating & this.HandshakeState) != this.HandshakeState)
                return _verification; // double

            // Set State
            this.HandshakeState = Handshake.State.Verificating;

            // Hello I am the one that is being connected to. So let's generate
            // the value M I should have in the SRPPackedData Object.
            Byte[] M = NetSRP.CalcM(N, g, _request.Username, _response.Salt, _request.A, _cache.B, _cache.K);

            // Compare
            if (!NetUtility.ArraysEqual(M, verification.M))
            {
                this.HandshakeState = Handshake.State.Denied | State.Failed;
                throw new NetSRP.HandShakeException("Invalid proof of Key. Username or password invalid.", new InvalidOperationException("Generated M does not match received M"));
            }

            // Ok, so their verification passed. Now let's proof that mine will to.
            _verification = new NetSRP.Verification(NetSRP.CalcM2(_request.A, verification.M, _cache.K));

            // Check expiration (maybe use timer?)
            if (_cache.ExpirationTime.CompareTo(DateTime.Now) < 0)
            {
                this.HandshakeState = Handshake.State.Expired;
                throw new NetSRP.HandShakeException("Hand was not shaken before it expired.");
            }

            return _verification;
        }