Пример #1
0
        public Task Deauthenticate()
        {
            AuthState  = AccountAuthState.Passivated;
            BPublic    = BigInteger.Zero;
            BPrivate   = BigInteger.Zero;
            SessionKey = BigInteger.Zero;

            return(Task.CompletedTask);
        }
Пример #2
0
        public async Task <SrpInitialParameters> GetSrpInitialParameters()
        {
            if (!IsExists)
            {
                throw new AccountDoesNotExistException($"account {this.GetPrimaryKeyString()} does not exist");
            }

            var random       = GrainFactory.GetGrain <IRandomService>(0);
            var randomNumber = await random.GetRandomBigInteger(16);

            var bPrivate = await random.GetRandomBigInteger(19);

            // put this after all awaits in case two requests' turns get interleaved
            if (AuthState != AccountAuthState.Passivated)
            {
                throw new AccountStateException("cannot generate new SRP parameters while a handshake is in progress or while authenticated");
            }

            BPrivate = bPrivate;
            BPublic  = ((State.Verifier * K) + BigInteger.ModPow(G, BPrivate, N)) % N;

            AuthState = AccountAuthState.ParametersGenerated;
            return(new SrpInitialParameters(BPublic, G, N, State.Salt, randomNumber));
        }
Пример #3
0
        public Task <SrpResult> SrpHandshake(BigInteger a, BigInteger m1)
        {
            if (!IsExists)
            {
                throw new AccountDoesNotExistException($"account {this.GetPrimaryKeyString()} does not exist");
            }
            if (AuthState != AccountAuthState.ParametersGenerated)
            {
                throw new AccountStateException("cannot handshake without first generating SRP initial parameters");
            }
            if (a.IsZero)
            {
                throw new SrpException("A cannot be zero");
            }
            if (BPublic.IsZero)
            {
                throw new SrpException("B cannot be zero");
            }

            using (var sha1 = new Digester(SHA1.Create()))
            {
                var u = BigIntegers.FromUnsignedByteArray(sha1.CalculateDigest(a, BPublic));
                var s = BigInteger.ModPow(a * BigInteger.ModPow(State.Verifier, u, N), BPrivate, N);

                var t  = s.ToByteArray(32);
                var t1 = new byte[16];
                var vK = new byte[40];

                // modified srp - uses a session key (vK, K) created by interleaving two hashes (tK) created from half (t1) of the shared secret (s)
                for (int i = 0; i < 16; ++i)
                {
                    t1[i] = t[i * 2];
                }
                var tK = sha1.CalculateDigest(t1);
                for (int i = 0; i < 20; ++i)
                {
                    vK[i * 2] = tK[i];
                }

                for (int i = 0; i < 16; ++i)
                {
                    t1[i] = t[i * 2 + 1];
                }
                tK = sha1.CalculateDigest(t1);
                for (int i = 0; i < 20; ++i)
                {
                    vK[i * 2 + 1] = tK[i];
                }

                SessionKey = BigIntegers.FromUnsignedByteArray(vK);

                var nghash = sha1.CalculateDigest(N.ToByteArray(32));
                var ghash  = sha1.CalculateDigest(new[] { G });

                for (int i = 0; i < sha1.DigestSize; ++i)
                {
                    nghash[i] ^= ghash[i];
                }

                var serverM1Bytes = sha1.CalculateDigest(new byte[][]
                {
                    nghash,
                    sha1.CalculateDigest(State.Name),
                    State.Salt.ToByteArray(32),
                    a.ToByteArray(32),
                    BPublic.ToByteArray(32),
                    vK,
                });

                // if client M1 matches server M1, then client and server have agreed on shared SessionKey, but only server knows that right now
                var serverM1 = BigIntegers.FromUnsignedByteArray(serverM1Bytes);
                if (serverM1 == m1)
                {
                    // need to send M2 so client knows session key is shared also
                    var m2Bytes = sha1.CalculateDigest(new byte[][]
                    {
                        a.ToByteArray(32),
                        serverM1Bytes,
                        SessionKey.ToByteArray(40),
                    });

                    AuthState = AccountAuthState.Authenticated;
                    var m2 = BigIntegers.FromUnsignedByteArray(m2Bytes);
                    return(Task.FromResult(new SrpResult(true, m2)));
                }
                else
                {
                    Deauthenticate().Wait();
                    return(Task.FromResult(new SrpResult(false, BigInteger.Zero)));
                }
            }
        }