2010-09-02 28 views
14

Necesito crear hash para la carpeta, que contiene algunos archivos. Ya hice esta tarea para cada uno de los archivos, pero busco la manera de crear un hash para todos los archivos en la carpeta. Alguna idea de como hacer eso?Creando hash para la carpeta

(por supuesto que puedo crear hash para cada archivo y concatenar a algún grande de hash, pero no es una manera de que me gusta)

Gracias de antemano.

Respuesta

1

Concatene los nombres de los archivos y el contenido de los archivos en una cadena grande y el hash, o realice el hashing en fragmentos para el rendimiento.

seguro de que necesita tener algunas cosas en cuenta:

  • Necesitas ordenar los archivos por nombre, por lo que no se produzcan dos hashes diferentes en el caso de los archivos de cambios de orden.
  • Con este método, solo tiene en cuenta los nombres de archivo y el contenido. si el nombre del archivo no cuenta, primero puede ordenar por contenido y luego por hash, si más atributos (ctime/mtime/hidden/archived ..) importan, inclúyalos en la secuencia que se va a codificar.
+0

Gracias por su respuesta. La cuerda puede ser muy grande, así que tendré que dividirla en trozos, solo pensando cómo hacerlo correctamente. –

+0

Recuerdo que los hashers de C# tenían una función para alimentarlos con trozos, y finalmente puedes pedir obtener el hash final, sin estar seguro de cuáles eran estas funciones/clases. Con ellos puede ordenar su entrada de la manera que desee en la memoria, luego buclear archivos y cargar fragmentos en unos cientos de KB y alimentarlos al hasher, de esta manera no necesita mucha memoria, pero aún así, tomará un tiempo para hash, que es algo de lo que no puedes deshacerte. – aularon

1

Si ya tiene valores hash para todos los archivos, simplemente ordene los hash alfabéticamente, concatenándolos y hash nuevamente para crear un hash uber.

7

Crear tarball de archivos, hash el tarball.

> tar cf hashes *.abc 
> md5sum hashes

O hash los archivos individuales y la salida de la tubería en el comando hash.

> md5sum *.abc | md5sum

Editar: ambos enfoques anteriores no ordenar los archivos por lo que pueden volver distinta de hash para cada invocación, dependiendo de cómo el shell expande asteriscos.

+0

+1 para el pensamiento creativo – Paedow

+0

+1 Este es realmente el enfoque directo :) –

+0

Esta es la única respuesta que también tiene en cuenta * todos * información meta como fechas, derechos de acceso, uids, guid, ... – itsafire

23

Esto comprime todas las rutas y contenidos de archivos (relativos) y maneja correctamente el orden de archivos.

Y es rápido, como 30ms para un directorio de 4MB.

using System; 
using System.Text; 
using System.Security.Cryptography; 
using System.IO; 
using System.Linq; 

... 

public static string CreateMd5ForFolder(string path) 
{ 
    // assuming you want to include nested folders 
    var files = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories) 
         .OrderBy(p => p).ToList(); 

    MD5 md5 = MD5.Create(); 

    for(int i = 0; i < files.Count; i++) 
    { 
     string file = files[i]; 

     // hash path 
     string relativePath = file.Substring(path.Length + 1); 
     byte[] pathBytes = Encoding.UTF8.GetBytes(relativePath.ToLower()); 
     md5.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0); 

     // hash contents 
     byte[] contentBytes = File.ReadAllBytes(file); 
     if (i == files.Count - 1) 
      md5.TransformFinalBlock(contentBytes, 0, contentBytes.Length); 
     else 
      md5.TransformBlock(contentBytes, 0, contentBytes.Length, contentBytes, 0); 
    } 

    return BitConverter.ToString(md5.Hash).Replace("-", "").ToLower(); 
} 
+0

Muy bueno de hecho –

+0

Tenga cuidado con el cumplimiento de FIPS si alguna vez implementa esto en un servidor con una Política de seguridad local que exige el cumplimiento de FIPS – SkeetJon

+0

@SkeetJon la técnica es la misma para cualquier algoritmo de cifrado, por lo que podría sustituir SHA para máquinas FIPS. –

9

Dunc's answer funciona bien; sin embargo, no maneja un directorio vacío. El código a continuación devuelve el MD5 'd41d8cd98f00b204e9800998ecf8427e' (el MD5 para una secuencia de caracteres de 0 longitud) para un directorio vacío.

public static string CreateDirectoryMd5(string srcPath) 
{ 
    var filePaths = Directory.GetFiles(srcPath, "*", SearchOption.AllDirectories).OrderBy(p => p).ToArray(); 

    using (var md5 = MD5.Create()) 
    { 
     foreach (var filePath in filePaths) 
     { 
      // hash path 
      byte[] pathBytes = Encoding.UTF8.GetBytes(filePath); 
      md5.TransformBlock(pathBytes, 0, pathBytes.Length, pathBytes, 0); 

      // hash contents 
      byte[] contentBytes = File.ReadAllBytes(filePath); 

      md5.TransformBlock(contentBytes, 0, contentBytes.Length, contentBytes, 0); 
     } 

     //Handles empty filePaths case 
     md5.TransformFinalBlock(new byte[0], 0, 0); 

     return BitConverter.ToString(md5.Hash).Replace("-", "").ToLower(); 
    } 
} 
+0

Si usa esta versión, querrá truncar 'filePath' en una ruta relativa para crear' pathBytes' con. –

Cuestiones relacionadas