Hashing rapido: combinazione di tecniche diverse per identificare le modifiche in un file?


9

Voglio creare un modo rapido per rilevare se un file potrebbe essere o meno lo stesso. Per quasi il 100% di sicurezza userei un algoritmo di hash esistente, ad esempio SHA256. Tuttavia, ci si aspetta che i file siano enormi file video con diversi GB, quindi il calcolo dell'hash SHA256 potrebbe richiedere del tempo, specialmente attraverso la rete.

Pertanto voglio combinare diverse altre tecniche:

  • dimensione del file: se la dimensione del file è cambiata, il contenuto è cambiato (sicuro)
  • hash testa / coda
  • hash casuale

Gli ultimi 2 fanno parte della mia domanda:

La mia ipotesi sarebbe che nell'intestazione ci siano cose come:

  • frame rate (ad es. video)
  • risoluzione (ad es. video, immagini)
  • (file) lunghezza (ad es. in cornici, pixel ecc.)
  • data dell'ultima modifica (ad es. documenti di Word, non specificamente video)

Perché prendo in considerazione il controllo della coda è:

  • MP3 ha le informazioni sui tag lì
  • EXIF aggiunge dati personalizzati alla fine, se ho ragione

Gli hash casuali selezionerebbero ad esempio 126 regioni in posizioni casuali nel file con una lunghezza specifica, ad esempio 64 kB e creerebbero un hash per loro. Ovviamente ricordo gli offset per un successivo confronto. Tutto sommato userei (1 + 126 + 1) * 64 kB di dati per il mio hash, quindi ho bisogno di leggere solo 8 MB invece di diversi GB per ottenere l'hash.

Forse è più una domanda matematica ora, ma: quanto è probabile rilevare un cambiamento usando la combinazione di dimensioni del file, testa, coda e dati casuali per generare questa somma hash veloce?

Presumo che i file siano sempre file legali. Non vi è alcun vantaggio nella manipolazione di singoli byte. L'utente utilizza un normale strumento di editing video per modificare i file.

AGGIORNAMENTO : non ho accettato questa risposta che proveniva da Crypto.StackExchange. Concordo sul fatto che la mia proposta non è crittografica e non intende essere sicura. Concordo anche sul fatto che CRCing di un file sia veloce, ma nel mio caso ho davvero bisogno di un hash - spiegherò perché:

  • La mia applicazione dovrebbe salvare i segnalibri nei video. Il mio database dovrebbe salvare l'hash del video e i segnalibri.
  • Gli utenti a volte spostano o rinominano i file. Il mio programma noterà che un file non esiste più, ma non eliminerà i segnalibri dal database. Invece, quando lo stesso video viene riprodotto (accidentalmente) di nuovo, voglio riconoscere che è (probabilmente) lo stesso file.
  • Gli utenti devono salvare i file su unità di rete (NAS) e trasmettere video in streaming. Quelli sono stupidi depositi. Non riesco a installare un componente server. E potrebbero essere abbastanza lenti, quindi non voglio davvero l'hash completo. Il calcolo di un hash completo su un file da 3 GB richiede almeno 5 minuti a 10 MB / s, indipendentemente dalla velocità dell'algoritmo di hashing.
  • Se l'utente ha modificato il file, spero in qualche modo che l'hash non corrisponda più, perché altrimenti visualizzerei segnalibri errati.

Starei bene con una probabilità dell'80% di avere i segnalibri corretti. Quanti pezzi di hash dovrei mettere insieme e dove nel file sarebbe?


1
Finché manomissioni o corruzione di file dannosi non sono un problema, non è necessario nulla di tutto ciò. Basta usare un programma specializzato per interpretare le intestazioni del file multimediale, che dovrebbe contenere le date e le dimensioni di codifica / tagging degli stream. È possibile eseguire l'hashing delle informazioni multimediali per un facile confronto.

Inoltre, la maggior parte dei sistemi operativi mantiene una "data dell'ultima modifica" disponibile per ciascun file. Se non devi preoccuparti di manomissioni dannose (l'ultima data modificata può essere generalmente impostata da qualcuno), puoi semplicemente guardarla e non preoccuparti del contenuto dei file.
poncho,

EXIF o MP3tag sono quasi inutili per rilevare le modifiche: molti programmi di manipolazione non sono in grado di toccarli e mantengono i loro contenuti precedenti. Ad esempio, EXIF ​​potrebbe conservare l' immagine originale .

1
Andando su "Suppongo che i file siano sempre file legali", immagino che non stai cercando alcuna sicurezza? In questo caso sei sul sito sbagliato. L'informatica dovrebbe essere un aiuto migliore. Le risposte che hai avuto qui sono irrilevanti se non vuoi la sicurezza, quindi in questo caso suggerirei di ripubblicare su Informatica e chiarire quel punto nella tua domanda ripubblicata.
Gilles 'SO- smetti di essere malvagio' il

2
1) Il calcolo effettivo dell'hash sarà generalmente economico rispetto all'IO. MD5 rileverà tutte le modifiche non dannose ed è piuttosto veloce. Soprattutto se lo parallelizzi. Avresti bisogno di un RAID di SSD o qualcosa di altrettanto veloce per superare la sua velocità. 2) Per i file locali il sistema operativo può spesso dirti se è cambiato. Non solo la data dell'ultima modifica, ci sono anche alcune API specializzate.
CodesInChaos,

Risposte:


8

La tua moneta ha due facce:

  1. se vuoi farlo sicuro, dovrai usare un hash crittograficamente sicuro come SHA256 (i cripto-hash sono pensati per essere veloci, ma tendono ad essere un po 'lenti a causa di vincoli di sicurezza),
  2. cose come i CRC sono decisamente più veloci, ma non saranno mai in grado di offrire lo stesso tipo di sicurezza (specialmente quando ne parliamo.

Opzione 1: CRC - Farlo rapidamente al prezzo della sicurezza:

Se stai subito dopo il rilevamento delle modifiche, scegli un checksum anziché un hash. Questo è ciò per cui sono stati fatti i checksum: rilevare rapidamente le modifiche in un file o flusso di dati. Ma tieni presente che CRC è stato progettato per prevenire errori di trasmissione, non azioni dannose!

In pratica, CRC32 è il candidato più ovvio (ma anche un additivo CRC8 farebbe il lavoro se si desidera rilevare solo se qualcosa è cambiato e non aspettarsi nient'altro da quello dal CRC.)

Opzione 2: oltre i CRC: farlo piuttosto rapidamente migliorando il rilevamento delle modifiche:

Altre opzioni valide (guardando il commento di @ poncho ) sono in realtà semplicemente controllare il timestamp dell'ultima mod .

Oppure, combinate entrambi (per evitare colli di bottiglia), usando qualcosa come questo pseudo-codice mostra:

if(LastMod != knownLastMod) { CreateNewCRCandCompare(FileName, knownCRC) };

Ma questo offre una vera sicurezza? No. Lo stesso vale per il tuo ...

Perché prendo in considerazione il controllo della coda è:
- MP3 contiene le informazioni sui tag lì
- EXIF ​​aggiunge dati personalizzati alla fine, se ho ragione

Ancora una volta, dipende da quanta sicurezza ti aspetti. Devi capire che un avversario manipolerà sicuramente il file per conservare (o copiare e incollare) tutti i vecchi dati ID3 ed EXIF ​​... in quanto chiunque (con i diritti di accesso ai file RW appropriati) può modificarlo. Lo stesso vale per il timestamp dell'ultima modifica, i frame rate, la risoluzione, la data dell'ultima modifica e persino la lunghezza (del file). A seconda di quei dati "aggiuntivi" e "modificabili" - che possono essere modificati e rimossi da chiunque disponga di diritti di accesso ai file sufficienti - introdurrebbe un difetto di sicurezza.

Ma ti aspetti sicurezza, vero? Dopo tutto, questo è il motivo per cui stai pensando a tutto questo in primo luogo. Bene, allora non c'è modo di aggirare l'uso di hash cripto-sicuri ...

Opzione 3: hash crittograficamente sicuri - Farlo in modo sicuro al prezzo della velocità:

Se ti aspetti una vera sicurezza, dovrai fare affidamento sull'hash; per essere più precisi: hash crittograficamente sicuro (usando un hash che non è noto per produrre collisioni). Ci vuole tempo (alcuni microsecs per MB) ma ne vale la pena.

I miei 2 centesimi (personali):

Prova a convivere con il fatto che l'hash costa tempo e hash di tutti i file con un hash crittograficamente sicuro . Perché, quando le cose iniziano a colpire il fan ... è meglio essere lenti, invece di essere dispiaciuti.

EDIT basato sul tuo EDIT ...

Se la sicurezza crittografica non è il tuo obiettivo principale, potresti guardare MD5 o SHA1. Sia MD5 che SHA1 sono "crittograficamente interrotti" perché sono state rilevate collisioni ... eppure per gli scopi di rilevamento del cambiamento che descrivi (specialmente dopo il tuo EDIT), la probabilità di colpire una tale collisione dovrebbe essere abbastanza minima.

Guardando di nuovo tutto (incluso il tuo EDIT), personalmente utilizzerei molto probabilmente MD5, perché offre una resistenza alle collisioni utilizzabile (per scopi di rilevamento delle modifiche) pur essendo abbastanza veloce da eseguire l'hashing completo dei file multi-gigabyte.

Se ciò non ti soddisfa ancora in un senso di "velocità" o se le tue risorse hardware sono davvero così limitate, devi provare a bilanciare la resistenza alle collisioni / il rilevamento delle modifiche con la velocità. Senso…

Prendi il singolo timestamp, il singolo nome file e l'hash dell'intestazione (la lunghezza dipende dal tipo di supporto e dal formato file utilizzato), nonché un buon pezzo dal centro e un buon pezzo di coda (= fine del file). Combina quei 5 e dovresti essere in grado di filtrare più o meno

Starei bene con una probabilità dell'80% di avere i segnalibri corretti. Quanti pezzi di hash dovrei mettere insieme e dove nel file sarebbe?

È più un'opinione personale, poiché dipende da un intero carico di dettagli (tipo di media, formato file, risorse disponibili, rapporto di rilevamento delle modifiche previsto, somiglianza dei file, ecc.), Quindi dovrai bilanciarlo da solo a seconda del tuo personale aspettative, implementazioni e risultati locali dovuti a strozzature hardware e / o software.

Lasciami provare a fornirti qualche consiglio:

Se l'hashing del file completo non è un'opzione per qualsiasi motivo, dovrei - almeno - prendere: l'intestazione (e forse qualche KB in più), un buon pezzo dal centro (almeno la dimensione del "header & co . ”) E un buon pezzo dalla fine del file (di nuovo, almeno la dimensione della parte“ header & co. ”).

Più risorse puoi investire (o sei disposto a investire), più pezzi puoi prendere e / o più grandi possono essere quei pezzi. Se pensi che le tue risorse / sensazioni / qualunque cosa offra ancora spazio per di più, aumenta la dimensione dei blocchi che hai e / o aumenta il numero di blocchi che hai.

Aumentare il numero di blocchi è semplice: tutto ciò che devi fare è occuparti di un'eguale distribuzione (dividendo la dimensione del file di conseguenza, ottenendo blocchi della stessa dimensione che estrai da parti equidistanti su tutta la lunghezza del file).

E se ti stai chiedendo "Perché distribuire equamente e non casuali posizioni di blocchi?", Fammi semplicemente notare che la selezione di posizioni di blocchi casuali potrebbe praticamente annullare i tuoi sforzi di rilevamento delle modifiche poiché incorpora il rischio di saltare alcune parti importanti dei media in cui normalmente rileveresti le possibilità che intendi rilevare. Scegliere una distribuzione equa è - semplicemente detto - più neutrale.


1
Non userei CRC32, troppe possibilità di fallimento anche senza attacchi dannosi. Crypto è piuttosto veloce. Dovresti ottenere 1 GB / s su un singolo core con un hash standard. Se lo indebolisci, dovrebbero essere possibili 3 GB / s. È quasi certo che l'IO sia più costoso dell'hash.
CodesInCos

@CodesInChaos Sono d'accordo. Ecco perché le mie parole di chiusura suggeriscono di optare per un hash crittograficamente sicuro.
e-sushi,

1
Gli hash Carter-Wegman e altri hash universali potrebbero aiutare. Questi hanno la velocità di un ampio CRC e la sicurezza degli hash, supponendo che una chiave rimanga sconosciuta all'attaccante e non venga riutilizzata. Vedi questa risposta per i riferimenti.
febbraio

@fgrieu Ma questo - in una situazione di OP - non significherebbe che OP avrebbe bisogno di una chiave individuale per file? Mi sembra poco pratico. In particolare, dal momento che introdurrebbe la necessità di una gestione delle chiavi ecc. Solo per verificare potenziali modifiche dei file.
e-sushi,

1
@ e-suschi: se esiste un identificatore di file univoco (come un percorso), è sufficiente una chiave master e HMAC per ottenere una chiave univoca per file. Detto questo, se l'avversario ottiene l'accesso in lettura alla chiave, può fare una falsificazione, quando non può con un hash regolare del file e l'accesso in sola lettura.
fgrieu,

5

Tasti di scelta rapida

Se si dispone di più file e si desidera rilevare le modifiche ai file, utilizzare la dimensione del file e il timestamp dell'ultima modifica.

È possibile che il sistema operativo utilizzato fornisca funzionalità per rilevare le modifiche ai file, ad esempio Linux consente di ricevere notifiche delle modifiche alle directory.

Elaborazione di file completa

Se devi leggere il contenuto effettivo dei file per verificare se i file sono cambiati, vai con l'hash crittografico reale. CRC ha un potenziale significativo di dare un falso negativo. SHA-256 può essere abbastanza buono, ma in realtà SHA-512 è più veloce su molte piattaforme moderne.

Se si dispone di molti core della CPU, potrebbe essere utile calcolare hash diversi per parti diverse del file o utilizzare la struttura hash per parallelizzare l'elaborazione.

Il motivo per cui viene suggerito l'hash corretto è che una volta passati ai dati dei file effettivi, l'elaborazione crittografica non sarà eccessiva, ma ci saranno molte altre cose più lente, in genere ad esempio l'I / O del disco o l'invio e la ricezione di pacchetti di rete.

Nota: per (almeno) file di piccole dimensioni è anche possibile archiviare l'intero contenuto del file ed effettuare un confronto del contenuto anziché dell'hash.

Nota 2: se la memoria è molto limitata, CRC o l'hash crittografico troncato potrebbero essere una buona scelta. CRC32 richiede 4 byte per file e SHA-256 è 32 byte. I tag di piccole dimensioni di 4 byte non sono in grado di proteggere dai tentativi di nascondere modifiche dannose.

Elaborazione di file parziale

Nella maggior parte dei casi, consiglierei di utilizzare solo l'elaborazione completa dei file.

Forse è più una domanda matematica ora, ma: quanto è probabile rilevare un cambiamento usando la combinazione di dimensione del file, testa, coda e dati casuali per generare questa somma hash veloce?

Per i file di immagine è comune apportare piccole modifiche, come rimuovere l'effetto occhi rossi, aggiungere baffi o corna, ecc. Queste modifiche in formato JPG a volte non influiscono sulla dimensione del file (con il programma di modifica che è in grado di apportare modifiche a JPG con la ricompressione solo modificata aree) o uno degli altri attributi menzionati.

Tuttavia, il tempo di modifica del file sarebbe interessato.

Considerando i file video: molti formati video generano un bit rate costante. Per i file a velocità di bit costante, se alcuni fotogrammi al centro vengono modificati, non verrà visualizzato anche in dimensioni, testa o coda del file. La rimozione o l'aggiunta di cornici comporterà quasi sempre differenze di dimensioni.

Quindi vedo del tutto possibile che quel campo riceva modifiche senza che venga rilevato.

È molto difficile stimare le modifiche di probabilità rilevate con questo schema, ma esistono scenari di utilizzo comuni per video e immagini che non vengono rilevati correttamente.


Sì, piccole modifiche sui file PNG o WAV hanno una grande possibilità di essere perse se vengono elaborati solo alcuni blocchi.
galinette,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.