/// <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); }