Gli hash MD5 consentiranno il rilevamento dei file sincronizzati?

5

Dobbiamo sviluppare il nostro sistema di gestione dei file nell'applicazione web Java. Abbiamo bisogno di sincronizzare i file tra il server principale e i server client e scoprire se tutto il server client ha l'ultima versione di file.

I nostri file sono in formato pdf, doc e xls e cambiano di tanto in tanto quando e quando richiesto.

Cosa stiamo pensando di utilizzare il checksum MD5 per scoprire l'hashcode dei file sul server principale e memorizzarlo nel database. Lo stesso sarebbe nel database dei server client. Dopo aver confrontato i record sul database, verremmo a sapere se i server client sono sincronizzati o meno.

Si prega di suggerire se ci sono modi migliori per fare lo stesso.

    
posta codpursue 04.02.2013 - 05:39
fonte

6 risposte

6

Sì, MD5 è quasi garantito per rilevare qualsiasi cambiamento nei file prodotti. Sono possibili attacchi di collisione (metodi per creare file diversi con identiche somme di hash), ma questa è solo una preoccupazione quando si sta combattendo contro un utente malintenzionato che sta tentando attivamente di produrli. Nel normale funzionamento questo non è un problema; il tuo errore hardware è molto, molto più probabile di una collisione accidentale.

Quindi, matematicamente, usare MD5 per gli algoritmi di sincronizzazione va bene. Ma come altri hanno sottolineato, potrebbero esserci soluzioni pronte che hanno più senso per te, oppure potrebbe essere troppo costoso scansionare regolarmente l'intero contenuto di ogni file, che dipende dalla tua particolare situazione ..

    
risposta data 04.02.2013 - 08:52
fonte
4

Informazioni sul nuovo concetto di design delle ruote: è stato fatto: rsync

utility software and network protocol for Unix-like systems (with ports to Windows) that synchronizes files and directories from one location to another while minimizing data transfer by using delta encoding when appropriate...

The recipient splits its copy of the file into fixed-size non-overlapping chunks and computes two checksums for each chunk: the MD5 hash, and a weaker 'rolling checksum'... It sends these checksums to the sender...

    
risposta data 04.02.2013 - 05:50
fonte
2

Se lo fai, ti consiglio di confrontare la dimensione in byte prima dell'hash MD5 (o altro).

Se la dimensione è diversa tra le due macchine, sai che il file è diverso. Non c'è bisogno di perdere tempo a calcolare un hash. E per la maggior parte dei tipi di file, compresi quelli che hai citato, è estremamente improbabile che una modifica ti lascerà esattamente con le stesse dimensioni del file.

    
risposta data 04.02.2013 - 11:59
fonte
2

Sì. Sai che tutti i file client sono sincronizzati dal server. Pertanto, se si conserva una cronologia sufficiente sul server, il client deve solo inviare il suo file versione . I calcoli MD5 costosi non sono necessari.

Nel caso (ipotetico) che un cliente possa aggiornare la sua copia, si ha comunque un problema molto più complicato. Non è possibile supportare modifiche concomitanti (non con Excel o PDF), quindi è necessario un sistema di check-out-modifica-controllo. A quel punto stai reinventando un VCS, quindi dovresti semplicemente scegliere SVN.

    
risposta data 04.02.2013 - 12:53
fonte
1

Potrebbe essere più facile ricordare quando i file sono stati sincronizzati l'ultima volta. Calcolare un hash per un file di grandi dimensioni potrebbe essere costoso. Se la data di modifica è successiva alla data di sincronizzazione su ciascuna macchina, il file deve essere nuovamente sincronizzato. Confrontare le date è economico e non dipende dalle dimensioni del file.

    
risposta data 04.02.2013 - 06:12
fonte
0

MD5 è detto abbastanza lento (vedi sotto). Il digest MD5 è piuttosto lungo. Suggerirei il tempo di modifica, la dimensione e il% di checksum diCRC-32 per i confronti tra file. Una discussione su CRC-32 è qui . Come suggerisce il nome, CRC-32 ha valori hash a 32 bit. Un'implementazione Java è disponibile in java.util.zip.CRC32

Modifica Il vantaggio di velocità di CRC-32 rispetto a MD5 è inferiore a quello che mi aspettavo. CRC-32 ha bisogno di circa il 20% di tempo in meno rispetto a MD5.

Ho usato il seguente codice Java per trovare la differenza (e demo l'uso di entrambi i metodi):

import java.security.*;
import java.util.Random;
import java.util.zip.CRC32;

public class HashBench {

    @SuppressWarnings("unused")
    public static void main(String[] args) throws Exception {
        int noOfLoopIterations = 100 * 1000;
        int bytesInMessageBuffer = 100 * 1024;

        byte randomByteBuffer[] = new byte[bytesInMessageBuffer];
        byte md5Digest[];
        MessageDigest md5;
        CRC32 crc;
        long crcValue;
        long startTime;     
        long elapsedTime;

        new Random().nextBytes(randomByteBuffer);

        //  MD5 benchmark
        o("Starting MD5 benchmark ...(" + bytesInMessageBuffer/1024 + "KByte messages)");
        md5 = MessageDigest.getInstance("MD5");

        startTime = System.nanoTime();
        for (int i = 1; i < noOfLoopIterations; i++)
        {
            md5Digest = md5.digest(randomByteBuffer);           
        }       
        showElapsed(noOfLoopIterations, startTime);

        //  CRC-32 benchmark
        o("Starting CRC-32 benchmark ... (" + bytesInMessageBuffer/1024 + "KByte messages)");
        crc = new CRC32();

        startTime = System.nanoTime();
        for (int i = 1; i < noOfLoopIterations; i++)
        {
            crc.reset();
            crc.update(randomByteBuffer);
            crcValue = crc.getValue();
        }       
        showElapsed(noOfLoopIterations, startTime);

        o("Ciao!");
    }

    private static void showElapsed(int noOfLoopIterations, long startTime) {
        long elapsedTime;
        elapsedTime = System.nanoTime() - startTime;
        o("Elapsed time:    " + num(elapsedTime / 1000000000.0) + "s for " + String.format("%1$,.0f", 1.0 * noOfLoopIterations) + " loops");
        o("Time per digest: " + num(elapsedTime / (1000000.0 * noOfLoopIterations)) + "ms");
        o("");
    }

    private static void o(String s) {
        System.out.println(s);
    }

    private static String num(double x) {
        return String.format("%1$,.2f", x);
    }

}

Il risultato:

Starting MD5 benchmark ...(100KByte messages)
Elapsed time:    28,94s for 100.000 loops
Time per digest: 0,29ms

Starting CRC-32 benchmark ... (100KByte messages)
Elapsed time:    23,89s for 100.000 loops
Time per digest: 0,24ms

Per evitare l'influenza del caching del disco e altri effetti esterni, riempio semplicemente un array di byte con valori casuali. Il benchmark esegue ripetutamente il calcolo dell'hash / checksum.

Conclusione: la velocità di calcolo non è un motivo convincente in questo caso.

    
risposta data 04.02.2013 - 23:36
fonte

Leggi altre domande sui tag