/// <summary> /// Calculates a hash value for the specified plaintext object and compares the result with the specified hash value. /// </summary> /// <param name="hash"> /// The hash value to evaluate. /// </param> /// <param name="plaintextObject"> /// The plaintext object to evaluate. /// </param> /// <param name="algorithm"> /// The algorithm specification used to transform the plaintext. /// </param> /// <param name="saltingMode"> /// A value specifying whether or not salt is applied to the plaintext. /// </param> /// <returns> /// <see langword="true" /> if the resulting hash value matches <paramref name="hash" />, otherwise <see langword="false" />. /// </returns> /// <exception cref="SecurityException"> /// An exception was raised during hashing or serialization. /// </exception> public Boolean EvaluateHash(Byte[] hash, T plaintextObject, HashingAlgorithmSpecification algorithm, SaltingMode saltingMode) { try { var digestLength = (algorithm.ToDigestBitLength() / 8); Byte[] processedHash; Byte[] calculatedHash; switch (saltingMode) { case SaltingMode.Salted: var salt = new Byte[SaltLengthInBytes]; processedHash = hash.Take(digestLength).ToArray(); salt = hash.Skip(digestLength).Take(SaltLengthInBytes).ToArray(); calculatedHash = CalculateHash(plaintextObject, algorithm, salt).Take(digestLength).ToArray(); break; default: processedHash = hash; calculatedHash = CalculateHash(plaintextObject, algorithm, null); break; } if (processedHash.Length != digestLength) { return(false); } else if (calculatedHash.Length != digestLength) { return(false); } for (var i = 0; i < digestLength; i++) { if (processedHash[i] == calculatedHash[i]) { continue; } return(false); } return(true); } catch { throw new SecurityException("The hashing operation failed."); } }
/// <summary> /// Calculates a hash value for the specified plaintext binary array. /// </summary> /// <param name="plaintextBinaryArray"> /// The plaintext binary array to hash. /// </param> /// <param name="algorithm"> /// The algorithm specification used to transform the plaintext. /// </param> /// <param name="salt"> /// The salt to apply to the plaintext, or <see langword="null" /> if the plaintext is unsalted. The default value is /// <see langword="null" />. /// </param> /// <returns> /// The resulting hash value. /// </returns> /// <exception cref="SecurityException"> /// An exception was raised during hashing or serialization. /// </exception> public Byte[] CalculateHash(Byte[] plaintextBinaryArray, HashingAlgorithmSpecification algorithm, Byte[] salt) { try { var applySalt = (salt is null == false); var saltLengthInBytes = (applySalt ? salt.Length : 0); var plaintextLengthInBytes = plaintextBinaryArray.Length; var plaintextBufferLengthInBytes = (plaintextLengthInBytes + saltLengthInBytes); var digestLengthInBytes = (algorithm.ToDigestBitLength() / 8); var hashLengthInBytes = (digestLengthInBytes + saltLengthInBytes); var hashValue = new Byte[hashLengthInBytes]; Byte[] plaintextBuffer; if (applySalt) { plaintextBuffer = new Byte[plaintextBufferLengthInBytes]; Array.Copy(plaintextBinaryArray, plaintextBuffer, plaintextLengthInBytes); Array.Copy(salt, 0, plaintextBuffer, plaintextLengthInBytes, saltLengthInBytes); } else { plaintextBuffer = plaintextBinaryArray; } using (var hashAlgorithm = algorithm.ToHashAlgorithm()) { Array.Copy(hashAlgorithm.ComputeHash(plaintextBinaryArray), hashValue, digestLengthInBytes); } if (applySalt) { Array.Copy(salt, 0, hashValue, digestLengthInBytes, saltLengthInBytes); } return(hashValue); } catch { throw new SecurityException("The hashing operation failed."); } }