Obtener el hash de un archivo

Esto es un ejemplo de como obtener distintos tipos de hash de un archivo,  me apoyaré en una de las nuevas características de C# 3.0, los métodos extensores, para tener más a mano esta funcionalidad. Como se puede ver en el código implementar nuevos métodos para la obtención de otros tipos de hash es sumamente sencillo.

Hay distintos tipos de hash, en este ejemplo he utilizado MD5y dos versiones de SHA, SHA-1 y SHA256. La necesidad y cualidades de cada uno nos dirán que usar en cada momento.

Estos métodos extienden la funcionalidad de la clase FileStream:

static class FileStreamExtensions
{
    public static String GetMd5Hash(this FileStream fs)
    {
        return getHash(fs, new MD5CryptoServiceProvider());
    }
 
    public static String GetSha1Hash(this FileStream fs)
    {
        return getHash(fs, new SHA1Managed());
    }
 
    public static String GetSha256Hash(this FileStream fs)
    {
        return getHash(fs, new SHA256Managed());
    }
 
    private static String getHash(FileStream fs, HashAlgorithm hash)
    {
        Int64 currentPos = fs.Position;
        try
        {
            fs.Seek(0, SeekOrigin.Begin);
            StringBuilder sb = new StringBuilder();
            foreach (Byte b in hash.ComputeHash(fs))
            {
                sb.Append(b.ToString("X2"));
            }
            return sb.ToString();
        }
        finally
        {
            fs.Seek(currentPos, SeekOrigin.Begin);
        }
    }
}

Cuando delcaremos el namespace de esta clase en nuestra unidad, podemos acceder a los métodos y obtener directamente el hash deseado de un tiro :D

static void Main(string[] args)
{
    FileStream fs = new FileStream(@"C:\mylife.mp3",FileMode.Open);
    Console.WriteLine(fs.GetMd5Hash());
    Console.WriteLine(fs.GetSha1Hash());
    Console.WriteLine(fs.GetSha256Hash());
    fs.Close();
    Console.ReadKey(true);
}

Si extendiesemos directamente la clase Stream tendriamos el problema de que a alguien se le podría ocurrir hacerlo sobre un NetworkStream... con lo que tendríamos una excepción ya que no todos los tipos de Stream soportan Seek ;)

 

Obtener el hash de un archivo | vtortola.NET
Published 7/3/2008 14:09 por Valeriano Tórtola
Archivado en: ,
Comparte este post:
http://geeks.ms/blogs/vtortola/archive/2008/03/07/obtener-el-hash-de-un-archivo.aspx

Comentarios

# re: Obtener el hash de un archivo

Esto es un ejemplo de porque no me gusta los extensores de métodos. Realizar un hash de un stream no es algo que tiene que involucrar al stream. El stream tiene su propósito. A veces a la gente se le olvida el principio de responsabilidad única.

Friday, March 7, 2008 5:31 PM por Anonimo

# re: Obtener el hash de un archivo

Bueno, te pueden gustar ó no gustar, lo que esta claro es lo útiles que son cuando se usan bien. El Stream tiene su función, como todas las clases del .NET Framework, cuando necesitas extender la funcionalidad... la extiendes :)


Realizar un hash de un Stream involucra al Stream, porque se obtiene un hash de ese mismo Stream. No veo el problema. Como realizar un Trim() de un String involucra al String. Únicamente estoy añadiendo una funcionalidad.

Friday, March 7, 2008 7:24 PM por Valeriano Tórtola

# re: Obtener el hash de un archivo

Si aplicas esa lógica, entonces crear una factura a un cliente debe ser también un método de la clase cliente?

Friday, March 7, 2008 7:35 PM por Anonimo

# re: Obtener el hash de un archivo

Según tu razonamiento el método .Trim() no debería ser un método de la clase String ?

Friday, March 7, 2008 7:42 PM por Valeriano Tórtola

# re: Obtener el hash de un archivo

Porque no debería serlo? Trim() es una función que claramente se aplica a una cadena. Es que según mi razonamiento si debería ser.

Friday, March 7, 2008 8:45 PM por Anonimo