/// <summary>
        ///     Checks if the string value is hashed in a collection of values.
        ///     <remarks>
        ///         Because the hashed values can be hashed in various ways, the value param
        ///         has to be hashed for each value. This can be slow but optimisations in this method
        ///         speeds this up.
        ///     </remarks>
        /// </summary>
        /// <param name="plaintext">The plain text value to check.</param>
        /// <param name="values">The collection of values to check in.</param>
        /// <returns></returns>
        public static bool IsInCollection(string plaintext, IEnumerable <HashedValue> values, ICryptoProvider saltProvider)
        {
            // keep track of the hashed representations of value in the various methods.
            var hashedValues = new List <HashedValue>();

            return(values.Any(
                       ph =>
            {
                var alreadyCalcd =
                    hashedValues.FirstOrDefault(
                        val => val.CanReuseSalt(ph));

                if (alreadyCalcd != null)
                {
                    return alreadyCalcd.HashString == ph.HashString;
                }

                var calc = new HashedValue(plaintext, ph);
                hashedValues.Add(calc);

                return calc.HashString == ph.HashString;
            }));
        }
 /// <summary>
 ///     Creates a hashed representation of the plain text.
 ///     This constructor uses the salt from the <see cref="oldHashedValue" /> in order to make comparison between
 ///     hashed values easier. This should be used with caution and is only recommended in instances such as
 ///     keeping a password history where you want to see if a password has been used before. If the hash has to
 ///     be calculated for each password in the history this could take a large amount of time.
 /// </summary>
 /// <param name="plainText">The text to hash</param>
 /// <param name="oldHashedValue">A hashed value in which to re-use the salt from.</param>
 /// <param name="saltProvider">Provider of the salt used for creating the hash.</param>
 private HashedValue(string plainText, HashedValue oldHashedValue)
 {
     _algorithm          = oldHashedValue.Algorithm;
     _complexityThrottle = oldHashedValue.ComplexityThrottle;
     ComputeHashWorker(plainText, _algorithm, _complexityThrottle, oldHashedValue.SaltBytes);
 }
 private bool Equals(HashedValue other)
 {
     return(HashString.Equals(other.HashString));
 }
 private bool CanReuseSalt(HashedValue value)
 {
     return(Algorithm == value.Algorithm && ComplexityThrottle == value.ComplexityThrottle && this.SaltBytes == value._saltBytes);
 }