Beispiel #1
0
        public SRP6a(Account account)
        {
            this.Account      = account;
            this.IdentitySalt = H.ComputeHash(Encoding.ASCII.GetBytes(this.Account.Email)).ToHexString(); // Identity salt that's hashed using account email.

            // calculate server's public ephemeral value.
            this.b = GetRandomBytes(128).ToBigInteger();                                                             // server's secret ephemeral value.
            var gModb = BigInteger.ModPow(g, b, N);                                                                  // pow(g, b, N)
            var k     = H.ComputeHash(new byte[0].Concat(N.ToArray()).Concat(g.ToArray()).ToArray()).ToBigInteger(); // Multiplier parameter (k = H(N, g) in SRP-6a

            this.B = BigInteger.Remainder((this.Account.PasswordVerifier.ToBigInteger() * k) + gModb, N);            // B = (k * v + pow(g, b, N)) % N

            // cook the logon challenge message
            this.LogonChallenge = new byte[0]
                                  .Concat(new byte[] { 0 })                // command = 0
                                  .Concat(this.IdentitySalt.ToByteArray()) // identity-salt - generated by hashing account email.
                                  .Concat(this.Account.Salt)               // account-salt - generated on account creation.
                                  .Concat(B.ToArray())                     // server's public ephemeral value (B)
                                  .Concat(SecondChallenge.ToArray())       // second challenge
                                  .ToArray();
        }
Beispiel #2
0
        /// <summary>
        /// Verifies the account using srp6a session provided values by client.
        /// </summary>
        /// <param name="ABytes">Client's public ephemeral</param>
        /// <param name="M_client">Client M.</param>
        /// <param name="seed">Session seed.</param>
        /// <returns></returns>
        public bool Verify(byte[] ABytes, byte[] M_client, byte[] seed)
        {
            var A = ABytes.ToBigInteger();                                                                                // client's public ephemeral
            var u = H.ComputeHash(new byte[0].Concat(ABytes).Concat(B.ToArray()).ToArray()).ToBigInteger();               // Random scrambling parameter - u = H(A, B)

            var S_s = BigInteger.ModPow(A * BigInteger.ModPow(this.Account.PasswordVerifier.ToBigInteger(), u, N), b, N); // calculate server session key - S = (Av^u) ^ b

            this.SessionKey = Calc_K(S_s.ToArray());                                                                      //  K = H(S) - Shared, strong session key.
            var K = this.SessionKey.ToBigInteger();

            var hashgxorhashN      = Hash_g_and_N_and_xor_them().ToBigInteger();                // H(N) ^ H(g)
            var hashedIdentitySalt = H.ComputeHash(Encoding.ASCII.GetBytes(this.IdentitySalt)); // H(I)

            var M = H.ComputeHash(new byte[0]                                                   // verify client M_client - H(H(N) ^ H(g), H(I), s, A, B, K_c)
                                  .Concat(hashgxorhashN.ToArray())
                                  .Concat(hashedIdentitySalt)
                                  .Concat(this.Account.Salt.ToArray())
                                  .Concat(ABytes)
                                  .Concat(B.ToArray())
                                  .Concat(K.ToArray())
                                  .ToArray());

            // We can basically move m_server, secondproof and logonproof calculation behind the M.CompareTo(M_client) check, but as we have an option DisablePasswordChecks
            // which allows authentication without the correct password, they should be also calculated for wrong-passsword auths. /raist.

            // calculate server proof of session key
            var M_server = H.ComputeHash(new byte[0] // M_server = H(A, M_client, K)
                                         .Concat(ABytes)
                                         .Concat(M_client)
                                         .Concat(K.ToArray())
                                         .ToArray());

            var secondProof = GetSecondProof(Encoding.ASCII.GetBytes(this.Account.Email), seed, SecondChallenge.ToArray());

            // cook logon proof message.
            LogonProof = new byte[0]
                         .Concat(new byte[] { 3 })      // command = 3 - server sends proof of session key to client
                         .Concat(M_server)              // server's proof of session key
                         .Concat(secondProof.ToArray()) // second proof
                         .ToArray();

            if (M.CompareTo(M_client)) // successful authentication session.
            {
                return(true);
            }
            else // authentication failed because of invalid credentals.
            {
                return(false);
            }
        }