using System; using System.IO; using System.Security.Cryptography; namespace FluentFTP { /// /// Represents a computed hash of an object /// on the FTP server. See the following link /// for more information: /// http://tools.ietf.org/html/draft-bryan-ftpext-hash-02 /// public class FtpHash { FtpHashAlgorithm m_algorithm = FtpHashAlgorithm.NONE; /// /// Gets the algorithm that was used to compute the hash /// public FtpHashAlgorithm Algorithm { get { return m_algorithm; } internal set { m_algorithm = value; } } string m_value = null; /// /// Gets the computed hash returned by the server /// public string Value { get { return m_value; } internal set { m_value = value; } } /// /// Gets a value indicating if this object represents a /// valid hash response from the server. /// public bool IsValid { get { return m_algorithm != FtpHashAlgorithm.NONE && !string.IsNullOrEmpty(m_value); } } /// /// Computes the hash for the specified file and compares /// it to the value in this object. CRC hashes are not supported /// because there is no built-in support in the .net framework and /// a CRC implementation exceeds the scope of this project. If you /// attempt to Verify() a CRC hash a NotImplemented() exception will /// be thrown. /// /// The file to compute the hash for /// True if the computed hash matches what's stored in this object. public bool Verify(string file) { using (FileStream istream = new FileStream(file, FileMode.Open, FileAccess.Read)) { return Verify(istream); } } /// /// Computes the hash for the specified stream and compares /// it to the value in this object. CRC hashes are not supported /// because there is no built-in support in the .net framework and /// a CRC implementation exceeds the scope of this project. If you /// attempt to Verify() a CRC hash a NotImplemented() exception will /// be thrown. /// /// The stream to compute the hash for /// True if the computed hash matches what's stored in this object. public bool Verify(Stream istream) { if (IsValid) { HashAlgorithm hashAlg = null; switch (m_algorithm) { case FtpHashAlgorithm.SHA1: #if CORE hashAlg = SHA1.Create(); #else hashAlg = new SHA1CryptoServiceProvider(); #endif break; #if !NET2 case FtpHashAlgorithm.SHA256: #if CORE hashAlg = SHA256.Create(); #else hashAlg = new SHA256CryptoServiceProvider(); #endif break; case FtpHashAlgorithm.SHA512: #if CORE hashAlg = SHA512.Create(); #else hashAlg = new SHA512CryptoServiceProvider(); #endif break; #endif case FtpHashAlgorithm.MD5: #if CORE hashAlg = MD5.Create(); #else hashAlg = new MD5CryptoServiceProvider(); #endif break; case FtpHashAlgorithm.CRC: throw new NotImplementedException("There is no built in support for computing CRC hashes."); default: throw new NotImplementedException("Unknown hash algorithm: " + m_algorithm.ToString()); } try { byte[] data = null; string hash = ""; data = hashAlg.ComputeHash(istream); if (data != null) { foreach (byte b in data) { hash += b.ToString("x2"); } return (hash.ToUpper() == m_value.ToUpper()); } } finally { #if !NET2 // .NET 2.0 doesn't provide access to Dispose() for HashAlgorithm if (hashAlg != null) hashAlg.Dispose(); #endif } } return false; } /// /// Creates an empty instance. /// internal FtpHash() { } } }