Quiero crear una forma rápida de detectar si un archivo puede o no ser el mismo. Para casi el 100% de seguridad, usaría un algoritmo hash existente, por ejemplo, SHA256. Sin embargo, se espera que los archivos sean archivos de video enormes con varios GB, por lo que calcular el hash SHA256 podría llevar algún tiempo, especialmente a través de la red.
Por lo tanto, quiero combinar otras técnicas diferentes:
- tamaño del archivo: si el tamaño del archivo ha cambiado, el contenido ha cambiado (seguro)
- hash de cabeza / cola
- hash aleatorio
Los últimos 2 son parte de mi pregunta:
Supongo que en el encabezado hay cosas como:
- velocidades de cuadro (por ejemplo, videos)
- resolución (por ejemplo, videos, imágenes)
- (archivo) longitud (por ejemplo, en cuadros, píxeles, etc.)
- última fecha de cambio (por ejemplo, documentos de Word, no específicamente videos)
Por qué considero revisar la cola es:
- MP3 tiene la información de la etiqueta allí
- EXIF agrega datos personalizados al final si tengo razón
Los hashes aleatorios seleccionarían, por ejemplo, 126 regiones en posiciones aleatorias en el archivo con una longitud específica, por ejemplo, 64 kB y crearían un hash para ellos. Por supuesto que recuerdo las compensaciones para una comparación posterior. En general, usaría (1 + 126 + 1) * 64 kB de datos para mi hash, por lo que necesito leer solo 8 MB en lugar de varios GB para obtener el hash.
Tal vez es más una pregunta matemática ahora, pero: ¿qué tan probable es detectar un cambio usando la combinación de tamaño de archivo, encabezado, cola y datos aleatorios para generar esta suma rápida de hash?
Supongo que los archivos son siempre archivos legales. No hay beneficio en la manipulación de bytes individuales. El usuario usaría una herramienta de edición de video normal para cambiar los archivos.
ACTUALIZACIÓN : no acepté esta respuesta que vino de Crypto.StackExchange. Estoy de acuerdo en que mi propuesta no es criptográfica y no pretende ser segura. También estoy de acuerdo en que CRCing un archivo es rápido, pero en mi caso realmente necesito un hash. Explicaré por qué:
- Se espera que mi aplicación guarde marcadores en videos. Se espera que mi base de datos guarde el hash de video y los marcadores.
- Los usuarios a veces mueven o renombran archivos. Mi programa notará que un archivo ya no existe, pero no eliminará los marcadores de la base de datos. En cambio, cuando el mismo video se reproduce (accidentalmente) nuevamente, quiero reconocer que es (probablemente) el mismo archivo.
- Se espera que los usuarios guarden archivos en unidades de red (NAS) y transmitan videos. Esos son almacenamientos tontos. No puedo instalar un componente del servidor. Y pueden ser bastante lentos, así que realmente no quiero el hash completo. Calcular un hash completo en un archivo de 3 GB lleva al menos 5 minutos a 10 MB / s, sin importar cuán rápido sea el algoritmo de hash.
- Si el usuario ha editado el archivo, de alguna manera espero que el hash no coincida más, porque de lo contrario mostraría marcadores incorrectos.
Estaría bien con un ~ 80% de posibilidades de tener los marcadores correctos. ¿Cuántas piezas hash debo juntar y en qué parte del archivo estarían?
fuente
Respuestas:
Hay dos caras de su moneda:
Opción 1: CRC: hacerlo rápidamente al precio de la seguridad:
Si está justo después de la detección de cambios, busque una suma de verificación en lugar de un hash. Para eso se hicieron las sumas de comprobación: detectar rápidamente los cambios en un archivo o flujo de datos. ¡Pero tenga en cuenta que CRC fue diseñado para evitar errores de transmisión, no acciones maliciosas!
Prácticamente, CRC32 es el candidato más obvio (pero incluso un CRC8 aditivo haría el trabajo si solo desea detectar si algo ha cambiado y no espera otra cosa que eso del CRC).
Opción 2: más allá de los CRC: hacerlo con bastante rapidez mientras se mejora la detección de cambios:
Otras opciones válidas (ver el comentario de @ poncho ) son simplemente verificar la marca de tiempo del último mod .
O combina ambos (para evitar cuellos de botella), usando algo como este pseudocódigo muestra:
Pero, ¿ofrece esto alguna seguridad real? No. Lo mismo va para tu ...
Nuevamente, depende de cuánta seguridad espere. Tiene que darse cuenta de que un adversario seguramente manipulará el archivo para mantener (o copiar y pegar) cualquier información ID3 y EXIF antigua ... ya que cualquiera (con los derechos de acceso a archivos RW apropiados) puede modificar eso. Lo mismo ocurre con la marca de tiempo de la última modificación, la velocidad de fotogramas, la resolución, la fecha del último cambio e incluso la longitud (del archivo). Dependiendo de que los datos "adicionales" y "modificables", que pueden ser modificados y eliminados por cualquier persona con suficientes derechos de acceso a los archivos, se introduciría una falla de seguridad.
Pero sí esperas seguridad, ¿no? Después de todo, esa es la razón por la que estás pensando en todo esto en primer lugar. Bueno, entonces no hay forma de evitar el uso de hashes cripto-seguros ...
Opción 3: hashes criptográficamente seguros: hacerlo de forma segura al precio de la velocidad:
Si espera seguridad real, tendrá que confiar en el hash; para ser más precisos: hashing criptográficamente seguro (usando un hash que no se sabe que produce colisiones). Lleva tiempo (unos microsecs por MB) pero vale la pena.
Mis 2 centavos (personales):
Trate de vivir con el hecho de que el hash cuesta tiempo y el hash de todos los archivos con un hash criptográficamente seguro . Porque, cuando las cosas comienzan a golpear al ventilador ... es mejor ser lento, en lugar de lamentar.
EDITAR en función de su EDITAR ...
Si la seguridad criptográfica no es su enfoque principal, puede mirar MD5 o SHA1. Tanto MD5 como SHA1 están "criptográficamente rotos" porque se han detectado colisiones ... sin embargo, para los fines de detección de cambios que describe (especialmente después de su EDIT), la probabilidad de golpear dicha colisión debería ser lo suficientemente mínima.
Mirando todo de nuevo (incluido su EDIT), lo más probable es que yo personalmente use MD5, ya que ofrece una resistencia a la colisión utilizable (para fines de detección de cambios) y al mismo tiempo es lo suficientemente rápido como para hash completamente archivos de varios gigabytes.
Si eso aún no lo satisface en un sentido de "velocidad" o si sus recursos de hardware son realmente tan limitados, debe intentar equilibrar la resistencia a colisiones / detección de cambios con la velocidad. Sentido…
Tome la marca de tiempo individual, el nombre de archivo individual y el encabezado hash (la longitud depende del tipo de medio y el formato de archivo utilizado), así como una buena porción del medio y una buena porción de la cola (= final del archivo). Combina esos 5 y deberías poder filtrar más o menos
Esa es más una opinión personal, ya que depende de una gran cantidad de detalles (tipo de medio, formato de archivo, recursos disponibles, relación de detección de cambio esperada, similitud de archivo, etc.), por lo que tendrá que equilibrarlo usted mismo dependiendo de su personal expectativas, sus implementaciones y resultados locales debido a cuellos de botella de hardware y / o software.
No obstante, permítame intentar brindarle alguna orientación:
Si el hash del archivo completo no es una opción por alguna razón, tomaría, al menos, el encabezado (y tal vez algunos KB más), una buena porción del medio (al menos el tamaño del "encabezado y código" . ") Y una buena parte del final del archivo (de nuevo, al menos el tamaño de la parte" header & co. ").
Cuantos más recursos pueda invertir (o esté dispuesto a invertir), más trozos puede tomar y / o más grandes pueden ser esos trozos. Si crees que tus recursos / sensación / lo que sea que todavía ofrece espacio para más, aumenta el tamaño de los fragmentos que hash y / o aumenta el número de fragmentos que hash.
Aumentar la cantidad de fragmentos es fácil: ya que todo lo que necesita hacer es cuidar una distribución equitativa (dividiendo el tamaño del archivo en consecuencia, lo que resulta en fragmentos del mismo tamaño que extrae de partes equidistantes en toda la longitud del archivo).
Y si se está preguntando "¿Por qué distribuir partes de fragmentos equitativamente y no al azar?", Permítanme señalar que elegir posiciones de fragmentos aleatorios prácticamente podría anular sus esfuerzos de detección de cambios, ya que incorpora el riesgo de omitir algunos medios importantes donde normalmente detectaría las posibilidades que intenta detectar. Elegir una distribución igual es, simplemente dicho, más neutral.
fuente
Atajos
Si tiene varios archivos y desea detectar cambios en los archivos, use el tamaño del archivo y la marca de tiempo de la última modificación.
Es posible que el sistema operativo que utiliza proporcione funciones para detectar cambios en los archivos, por ejemplo, Linux permite recibir notificaciones de cambios en los directorios.
Procesamiento completo de archivos
Si necesita leer el contenido real de los archivos para verificar si los archivos han cambiado, vaya con el hash criptográfico real. CRC tiene un potencial significativo de dar un falso negativo. SHA-256 puede ser bastante bueno, pero en realidad, SHA-512 es más rápido en muchas plataformas modernas.
Si tiene muchos núcleos de CPU, podría ser útil calcular diferentes hashes para diferentes partes del archivo o usar un árbol de hash para paralelizar el procesamiento.
La razón para sugerir un hash adecuado es que una vez que accede a los datos reales del archivo, el procesamiento criptográfico no será demasiado, en su lugar habrá muchas otras cosas más lentas, por ejemplo, E / S de disco o envío y recepción de paquetes de red.
Nota: Para (al menos) archivos pequeños, también es posible almacenar el contenido completo del archivo y hacer una comparación de los contenidos en lugar de hash.
Nota 2: Si tiene poco espacio de almacenamiento, CRC o hash criptográfico truncado podría ser una buena opción. CRC32 toma 4 bytes por archivo, y SHA-256 es de 32 bytes. Las etiquetas pequeñas de 4 bytes no pueden proteger contra intentos maliciosos de ocultar ediciones.
Procesamiento parcial de archivos
En la mayoría de los casos, recomendaría usar solo el procesamiento completo de archivos.
Para los archivos de imagen, es común hacer pequeñas ediciones, como eliminar ojos rojos, agregar bigote o cuernos, etc. Estas ediciones en formato JPG ocasionalmente no afectarían el tamaño del archivo (con el programa de edición que puede hacer cambios a JPG con la recompresión solo alterada áreas) o uno de los otros atributos que menciona.
Sin embargo, el tiempo de modificación del archivo generalmente se vería afectado.
Considerando los archivos de video: muchos formatos de video generan una tasa de bits constante. Para el archivo de velocidad de bits constante, si se alteran algunos cuadros en el medio, tampoco aparecerá en el tamaño del archivo, la cabeza o la cola. Eliminar o agregar marcos casi siempre resultará en una diferencia de tamaño.
Por lo tanto, veo que es posible que el campo obtenga cambios sin que se detecte.
Es muy difícil estimar las ediciones de probabilidad que se detectan con este esquema, pero hay escenarios de uso comunes para videos e imágenes que no se detectan correctamente.
fuente