Hash rápido: combinação de diferentes técnicas para identificar alterações em um arquivo?

9

Quero criar uma maneira rápida de detectar se um arquivo pode ou não ser o mesmo. Para quase 100% de certeza, eu usaria um algoritmo de hash existente, por exemplo, SHA256. No entanto, espera-se que os arquivos sejam enormes arquivos de vídeo com vários GB, portanto, o cálculo do hash SHA256 pode levar algum tempo, especialmente na rede.

Portanto, eu quero combinar diferentes outras técnicas:

  • tamanho do arquivo: se o tamanho do arquivo foi alterado, o conteúdo foi alterado (com certeza)
  • hash cabeça / cauda
  • mistura aleatória

Os dois últimos fazem parte da minha pergunta:

Meu palpite seria que no cabeçalho existem coisas como:

  • taxas de quadros (por exemplo, vídeos)
  • resolução (por exemplo, vídeos, imagens)
  • (arquivo) comprimento (por exemplo, em quadros, pixels etc.)
  • data da última alteração (por exemplo, documentos do Word, não especificamente vídeos)

Por que considero verificar a cauda é:

  • O MP3 contém as informações da etiqueta
  • EXIF adiciona dados personalizados no final, se eu estiver certo

Os hashes aleatórios selecionariam, por exemplo, 126 regiões em posições aleatórias no arquivo com um comprimento específico, por exemplo, 64 kB e criariam um hash para elas. É claro que me lembro das compensações para comparação posterior. No geral, eu usaria (1 + 126 + 1) * 64 kB de dados para meu hash, portanto, preciso ler apenas 8 MB em vez de vários GB para obter o hash.

Talvez seja mais uma questão de matemática agora, mas: qual a probabilidade de detectar uma alteração usando a combinação de tamanho do arquivo, cabeçalho, cauda e dados aleatórios para gerar essa soma rápida de hash?

Presumo que os arquivos sejam sempre legais. Não há benefício em manipular bytes únicos. O usuário usaria uma ferramenta normal de edição de vídeo para alterar os arquivos.

UPDATE : Eu aceitei esta resposta que veio do Crypto.StackExchange. Concordo que minha proposta não é criptográfica e não pretende ser segura. Também concordo que o CRC de um arquivo é rápido, mas no meu caso eu realmente preciso de um hash - vou explicar o porquê:

  • Espera-se que meu aplicativo salve marcadores em vídeos. Espera-se que meu banco de dados salve o hash do vídeo e os favoritos.
  • Às vezes, os usuários movem ou renomeiam arquivos. Meu programa notará que um arquivo não existe mais, mas não excluirá os indicadores do banco de dados. Em vez disso, quando o mesmo vídeo é (acidentalmente) reproduzido novamente, quero reconhecer que é (provavelmente) o mesmo arquivo.
  • Os usuários devem salvar arquivos em unidades de rede (NAS) e transmitir vídeos. Esses são estúpidos armazéns. Não consigo instalar um componente do servidor. E eles podem ser bem lentos, então eu realmente não quero o hash completo. O cálculo de um hash completo em um arquivo de 3 GB leva pelo menos 5 minutos a 10 MB / s, independentemente da velocidade do algoritmo de hash.
  • Se o usuário tiver editado o arquivo, espero, de alguma forma, que o hash não corresponda mais, porque, caso contrário, eu exibiria indicadores errados.

Eu ficaria bem com uma chance de ~ 80% de ter os marcadores corretos. Quantas peças de hash eu devo montar e onde estaria o arquivo?

Thomas Weller
fonte
1
Desde que a adulteração maliciosa ou a corrupção de arquivos não sejam uma preocupação, não há necessidade disso. Basta usar um programa especializado para interpretar os cabeçalhos dos arquivos de mídia, que devem conter as datas e os tamanhos de codificação / codificação dos fluxos. Você pode misturar as informações da mídia para facilitar a comparação.
Além disso, a maioria dos sistemas operacionais mantém uma 'data da última modificação' disponível para cada arquivo. Se você não precisar se preocupar com adulteração mal-intencionada (essa data da última modificação geralmente pode ser definida por alguém), basta olhar para isso e não se preocupar com o conteúdo de nenhum arquivo.
Poncho
EXIF ou MP3tag são quase inúteis para detectar alterações: Muitos dos programas de manipulação não conseguem tocá-los, mantendo o conteúdo anterior. Por exemplo, EXIF ​​pode muito bem manter a imagem original .
1
Indo "Presumo que os arquivos sempre sejam legais", acho que você não está procurando por segurança? Nesse caso, você está no site errado. Ciência da Computação deve ser uma ajuda melhor. As respostas que você teve aqui são irrelevantes se você não quer segurança, por isso, se esse for o caso, sugiro que repassemos a Ciência da Computação e esclareçamos esse ponto em sua pergunta reeditada.
Gilles 'SO- stop be evil'
2
1) O cálculo de hash real geralmente será barato comparado ao IO. O MD5 detectará todas as alterações não maliciosas e é muito rápido. Especialmente se você fizer um paralelo. Você precisaria de um RAID de SSDs ou algo semelhante rápido para exceder sua velocidade. 2) Para arquivos locais, o sistema operacional geralmente pode dizer se foi alterado. Não apenas a data da última alteração, também existem algumas APIs especializadas.
CodesInChaos

Respostas:

8

Existem dois lados da sua moeda:

  1. se você quiser protegê-lo, precisará usar um hash criptograficamente seguro como o SHA256 (os hash criptográficos devem ser rápidos, mas tendem a ser um pouco lentos devido a restrições de segurança),
  2. coisas como CRCs são definitivamente mais rápidas, mas nunca serão capazes de oferecer o mesmo tipo de segurança (principalmente quando falamos sobre isso).

Opção 1: CRCs - Faça isso rapidamente pelo preço da segurança:

Se você estiver logo após a detecção de alterações, escolha uma soma de verificação em vez de um hash. É para isso que as somas de verificação foram feitas: detecção rápida de alterações em um arquivo ou fluxo de dados. Mas lembre-se de que o CRC foi projetado para evitar erros de transmissão, não ações maliciosas!

Praticamente, o CRC32 é o candidato mais óbvio (mas mesmo um CRC8 aditivo faria o trabalho se você quiser apenas detectar se algo mudou e não esperar nada além do CRC).

Opção 2: Além dos CRCs - faça isso rapidamente e aprimore a detecção de alterações:

Outras opções válidas (olhando para o comentário do @ poncho ) são, de fato, simplesmente verificar o carimbo de data / hora da última modificação .

Ou você combina os dois (para evitar gargalos), usando algo como este pseudo-código mostra:

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

Mas isso oferece alguma segurança real? Não. O mesmo vale para o seu…

Por que considero verificar a cauda é:
- O MP3 contém as informações da etiqueta
- EXIF ​​adiciona dados personalizados no final, se eu estiver certo

Novamente, depende de quanta segurança você espera. Você deve perceber que um adversário certamente manipulará o arquivo para manter (ou copiar e colar) todos os dados ID3 e EXIF ​​antigos ... como qualquer pessoa (com direitos apropriados de acesso a arquivos RW) pode modificar isso. O mesmo vale para o carimbo de data / hora da última modificação, taxas de quadros, resolução, data da última alteração e até o tamanho (do arquivo). Dependendo dos dados "adicionais" e "modificáveis" - que podem ser modificados e removidos por qualquer pessoa com direitos suficientes de acesso a arquivos -, seria introduzida uma falha de segurança.

Mas você espera segurança, não é? Afinal, essa é a razão pela qual você está pensando sobre tudo isso em primeiro lugar. Bem, então não há como usar hashes criptografados ...

Opção 3: Hashes criptograficamente seguros - Faça com segurança ao preço da velocidade:

Se você espera segurança real, precisará confiar no hash; para ser mais preciso: hash criptograficamente seguro (usando um hash que não é conhecido por produzir colisões). Leva tempo (alguns microssegundos por MB), mas vale a pena.

Meus 2 centavos (pessoais):

Tente viver com o fato de que o hash custa tempo e mistura todos os arquivos com um hash criptograficamente seguro . Porque, quando as coisas começam a bater no ventilador ... é melhor você ser lento, em vez de se arrepender.

EDIT com base no seu EDIT…

Se a segurança criptográfica não for seu foco principal, você pode olhar para MD5 ou SHA1. Tanto o MD5 quanto o SHA1 são "criptograficamente danificados" porque as colisões foram detectadas ... mas, para os fins de detecção de alterações que você descreve (especialmente após sua EDIT), a probabilidade de atingir tal colisão deve ser mínima o suficiente.

Olhando para tudo novamente (incluindo o seu EDIT), eu provavelmente usaria o MD5, porque oferece uma resistência à colisão utilizável (para fins de detecção de alterações) e ainda é rápido o suficiente para misturar completamente arquivos de vários gigabytes.

Se isso ainda não satisfazê-lo em um sentido “velocidade” ou se os seus recursos de hardware são realmente que limitado, você tem que tentar equilibrar alteração de detecção de colisões resistência / com velocidade. Significado…

Pegue o carimbo de data / hora individual, o nome do arquivo individual e o cabeçalho do hash (o comprimento depende do tipo de mídia e do formato do arquivo usado), bem como um bom pedaço do meio e um bom pedaço do final (= final do arquivo). Combine os 5 e você poderá filtrar a maioria dos

Eu ficaria bem com uma chance de ~ 80% de ter os marcadores corretos. Quantas peças de hash eu devo montar e onde estaria o arquivo?

Essa é mais uma opinião pessoal, pois depende de uma grande quantidade de detalhes (tipo de mídia, formato de arquivo, recursos disponíveis, taxa de detecção de alterações esperada, semelhança de arquivo etc.). expectativas, suas implementações e resultados locais devido a gargalos de hardware e / ou software.

Deixe-me tentar fornecer algumas orientações, no entanto:

Se o hashing do arquivo completo não for uma opção por qualquer motivo, eu aceitaria - pelo menos: o cabeçalho (e talvez alguns KBs a mais), uma boa parte do meio (pelo menos o tamanho do cabeçalho . ”) E uma boa parte do final do arquivo (novamente, pelo menos o tamanho da parte“ header & co. ”).

Quanto mais recursos você puder investir (ou estiver disposto a investir), mais trechos você poderá usar e / ou maiores serão esses trechos. Se você acha que seus recursos / sensação / o que ainda oferece espaço para mais, aumente o tamanho dos pedaços que você hash e / ou aumente o número de pedaços que você hash.

Aumentar o número de partes é fácil: tudo o que você precisa fazer é cuidar de uma distribuição igual (dividindo o tamanho do arquivo adequadamente, resultando em partes do mesmo tamanho que você extrai de partes igualmente espaçadas em todo o comprimento do arquivo).

E se você está se perguntando "Por que distribuir partes aleatoriamente distribuídas e não aleatórias?", Deixe-me observar que escolher posições aleatórias de partes pode praticamente invalidar seus esforços de detecção de alterações, uma vez que incorpora o risco de pular algumas partes importantes da mídia onde você normalmente detectaria as chances que está tentando detectar. Escolher uma distribuição igual é - simplesmente dito - mais neutro.

e-sushi
fonte
1
Eu não usaria o CRC32, muito grande chance de falha, mesmo sem ataques maliciosos. Criptografia é bem rápida. Você deve obter 1 GB / s em um único núcleo com um hash padrão. Se você enfraquecer um pouco, 3 GB / s deve ser possível. É quase certo que o IO seja mais caro que o hash.
CodesInChaos
@CodesInChaos Concordo. É por isso que minhas palavras finais aconselham a optar por um hash criptograficamente seguro.
e-sushi
1
Os hashes Carter-Wegman e outros hashes universais podem ajudar. Eles têm a velocidade de uma ampla CRC e a segurança de hashes, supondo que uma chave permaneça desconhecida pelo invasor e não seja reutilizada. Veja esta resposta para referências.
fgrieu
@grgrieu Mas isso não significa que, na situação dos OPs, os OP precisariam de uma chave individual por arquivo? Parece um pouco impraticável para mim. Especialmente, uma vez que introduziria a necessidade de gerenciamento de chaves, etc., apenas para verificar possíveis modificações no arquivo.
e-sushi
1
@ e-suschi: se houver algum identificador de arquivo exclusivo (como um caminho), uma chave mestra e o HMAC serão necessários para obter uma chave exclusiva por arquivo. Dito isto, se o adversário obtém acesso de leitura à chave, ele pode fazer uma falsificação, quando não puder com um hash regular do arquivo e acesso somente leitura.
fgrieu
5

Atalhos

Se você possui vários arquivos e deseja detectar alterações nos arquivos, use o tamanho do arquivo e o carimbo de data e hora da última modificação.

É possível que o sistema operacional usado forneça recursos para detectar alterações de arquivos, por exemplo, o Linux permite obter notificações de alterações nos diretórios.

Processamento completo de arquivos

Se você precisar ler o conteúdo real dos arquivos para verificar se os arquivos foram alterados, use o hash criptográfico real. A CRC tem um potencial significativo de dar um falso negativo. O SHA-256 pode ser muito bom, mas, na verdade, o SHA-512 é mais rápido em muitas plataformas modernas.

Se você tiver muitos núcleos de CPU, pode ser útil calcular hashes diferentes para diferentes partes do arquivo ou usar a árvore de hash para paralelizar o processamento.

O motivo para sugerir o hash adequado é que, depois de acessar os dados reais do arquivo, o processamento criptográfico não será muito grande; em vez disso, haverá muitas outras coisas mais lentas, como por exemplo, E / S de disco ou envio e recebimento de pacotes de rede.

Nota: Para (pelo menos) arquivos pequenos, também é possível armazenar todo o conteúdo do arquivo e comparar o conteúdo em vez do hash.

Nota 2: Se você tem muito armazenamento, o CRC ou o hash criptográfico truncado pode ser uma boa opção. O CRC32 ocupa 4 bytes por arquivo e o SHA-256 tem 32 bytes. Tags pequenas de 4 bytes não conseguem proteger contra tentativas maliciosas de ocultar edições.

Processamento parcial de arquivo

Na maioria dos casos, eu recomendaria usar apenas o processamento completo do arquivo.

Talvez seja mais uma questão de matemática agora, mas: qual a probabilidade de detectar uma alteração usando a combinação de tamanho do arquivo, cabeçalho, cauda e dados aleatórios para gerar essa soma rápida de hash?

Para arquivos de imagem, é comum fazer pequenas edições, como remover olhos vermelhos, adicionar bigode ou buzinas, etc. Essas edições no formato JPG ocasionalmente não afetam o tamanho do arquivo (com o programa de edição capaz de fazer alterações no JPG com a recompressão apenas alterada) áreas) ou um dos outros atributos mencionados.

O tempo de modificação do arquivo geralmente seria afetado.

Considerando arquivos de vídeo: muitos formatos de vídeo geram taxa de bits constante. Para um arquivo de taxa de bits constante, se alguns quadros no meio forem alterados, ele também não aparecerá no tamanho, cabeçalho ou cauda do arquivo. Remover ou adicionar molduras quase sempre resultará em diferenças de tamanho.

Então, vejo que é totalmente possível que o campo obtenha alterações sem que seja detectado.

É muito difícil estimar que as edições de probabilidade sejam detectadas com esse esquema, mas existem cenários de uso comuns para vídeos e imagens que não são detectados corretamente.


fonte
Sim, pequenas edições em arquivos PNG ou WAV têm uma grande chance de serem perdidas se apenas alguns pedaços forem processados.
galinette