public void TestGenerateAndCompareHashMatch()
        {
            byte[] saltAndHash = Convert.FromBase64String(PasswordHashing.EncodePassword(KnownPassword.ToSecureString(), null));
            byte[] salt        = PasswordHashing.ExtractStoredSalt(saltAndHash);

            Assert.That(salt, Is.Not.Null);
            Assert.That(PasswordHashing.HashesMatch(Convert.FromBase64String(PasswordHashing.EncodePassword(KnownPassword.ToSecureString(), salt)), saltAndHash));
        }
        public void TestHashMatches()
        {
            byte[] storedHash = Convert.FromBase64String(KnownHashAndSalt);
            byte[] salt       = PasswordHashing.ExtractStoredSalt(storedHash);
            byte[] curHash    = Convert.FromBase64String(PasswordHashing.EncodePassword(KnownPassword.ToSecureString(), salt));

            Assert.That(PasswordHashing.HashesMatch(storedHash, curHash), Is.True);
        }
        public void TestHashDoesntMatch()
        {
            byte[] storedHash = Convert.FromBase64String(KnownHashAndSalt);
            byte[] salt       = PasswordHashing.GenerateSalt();
            byte[] curHash    = Convert.FromBase64String(PasswordHashing.EncodePassword(KnownPassword.ToSecureString(), salt));

            Assert.That(PasswordHashing.HashesMatch(storedHash, curHash), Is.False);
        }
Exemple #4
0
        /// <summary>
        /// Retrieve user information after validating provided userId and passphrase.
        /// If valid then returns true and updates user with UserDetails
        /// Otherwise returns false and sets user to null
        /// </summary>
        /// <param name="userId"></param>
        /// <param name="passphrase"></param>
        /// <param name="user">creates new instance and returns validated user information</param>
        /// <returns>true if user input valid and user object container user information; false on any error validating</returns>
        public bool ValidateUser(string userId, SecureString passphrase, out UserDetail user)
        {
            logger.Trace(nameof(ValidateUser));
            // ensure we initialize user to null unless a valid userId and passphrase is provided
            user = null;

            // if not a valid value for DB key then fail early
            if (string.IsNullOrWhiteSpace(userId))
            {
                return(false);
            }

            try
            {
                // retrieve corresponding user information from DB
                // Note: userId [UserDetail DB table key] is stored in lower case (using CultureInvariant form)
                var possibleUser = GetUserDetailsFor(userId);
                // invalid userId or error loading from DB - failed to validate; Note early exit allows determination of usernames
                if (possibleUser == null)
                {
                    logger.Warn($"Failed to obtain possible user details for {userId}.");
                    return(false);
                }

                // get attempted password, exit early if obviously invalid passphrase (blank)
                // if (string.IsNullOrWhiteSpace(passphrase.ToString())) return false; -- passphrase is now a SecureString, don't defeat point and convert to string
                if ((passphrase == null) || (passphrase.Length < 1))
                {
                    logger.Warn($"Passphrase provided for {userId} is invalid.");
                    return(false);
                }

                // split apart stored hash so we can hash attempted password & compare
                bool isValid;
                try
                {
                    byte[] storedHash = Convert.FromBase64String(possibleUser.hashedPassphrase);
                    byte[] salt       = PasswordHashing.ExtractStoredSalt(storedHash);
                    // get hashed version of attempted password
                    byte[] curHash = Convert.FromBase64String(PasswordHashing.EncodePassword(passphrase, salt));

                    // determine if hashed passphrases are a match
                    isValid = PasswordHashing.HashesMatch(storedHash, curHash);
                }
                catch (System.FormatException e) // invalid Base64 string
                {
                    logger.Warn("Error validating credentials, likely stored passphrase corrupted / not base64 encoded!", e);
                    isValid = false;
                }
                // validated supplied password, now confirm user account not currently disabled
                isValid = isValid && possibleUser.isActive;

                // only return any information if user credentials successfully validated
                if (isValid)
                {
                    logger.Info("Valid user.");
                    user = possibleUser;
                }
                else
                {
                    logger.Warn($"Failed to validate credentials for user {userId}.");
                }

                return(isValid);
            }
            catch (Exception e)
            {
                logger.Error(e, $"Error occured when validating user - {e.Message}");
                throw;
            }
        }