¿Hay alguna forma simple de generar (y verificar) sumas de verificación MD5 de una lista de archivos en Python? (Tengo un pequeño programa en el que estoy trabajando y me gustaría confirmar las sumas de verificación de los archivos).
348
md5sum
?md5sum
. Es por eso que los programadores conscientes de la seguridad no deberían usarlo en mi opinión.md5sum
Deben evitarse ambas y la técnica descrita en esta pregunta SO: es mejor usar SHA-2 o SHA-3, si es posible: en.wikipedia.org/wiki/Secure_Hash_AlgorithmsRespuestas:
Puede usar hashlib.md5 ()
Tenga en cuenta que a veces no podrá ajustar todo el archivo en la memoria. En ese caso, tendrá que leer fragmentos de 4096 bytes secuencialmente y alimentarlos al
md5
método:Nota:
hash_md5.hexdigest()
devolverá la representación de cadena hexadecimal para el resumen, si solo necesita el uso de bytes empaquetadosreturn hash_md5.digest()
, para que no tenga que volver a convertir.fuente
Hay una manera que es bastante ineficiente de memoria .
archivo único:
lista de archivos:
Recordemos, sin embargo, que MD5 se sabe roto y no debe ser utilizado para cualquier propósito ya que el análisis de la vulnerabilidad puede ser muy difícil, y el análisis de cualquier posible uso futuro de su código podría ser condenado a las cuestiones de seguridad es imposible. En mi humilde opinión, debe eliminarse completamente de la biblioteca para que todos los que lo usen se vean obligados a actualizar. Entonces, esto es lo que debes hacer en su lugar:
Si solo quieres 128 bits de digestión, puedes hacerlo
.digest()[:16]
.Esto le dará una lista de tuplas, cada tupla contiene el nombre de su archivo y su hash.
Nuevamente, cuestiono mucho su uso de MD5. Al menos debería usar SHA1, y dados los defectos recientes descubiertos en SHA1 , probablemente ni siquiera eso. Algunas personas piensan que mientras no esté usando MD5 para propósitos 'criptográficos', está bien. Pero las cosas tienden a tener un alcance más amplio de lo que inicialmente esperaba, y su análisis de vulnerabilidad casual puede resultar completamente defectuoso. Es mejor acostumbrarse a usar el algoritmo correcto desde el principio. Simplemente escribir un grupo diferente de letras es todo. No es tan dificil.
Aquí hay una manera que es más compleja, pero eficiente en memoria :
Y, de nuevo, dado que MD5 está roto y ya no debería usarse nunca más:
Una vez más, puede poner
[:16]
después de la llamada ahash_bytestr_iter(...)
si solo desea un resumen de 128 bits.fuente
Claramente, no agrego nada fundamentalmente nuevo, pero agregué esta respuesta antes de comentar el estado, además de que las regiones de código aclaran las cosas, de todos modos, específicamente para responder a la pregunta de @ Nemo de la respuesta de Omnifarious:
Estaba pensando un poco en las sumas de comprobación (vine aquí buscando sugerencias sobre tamaños de bloque, específicamente), y descubrí que este método puede ser más rápido de lo que cabría esperar. Tomando el más rápido (pero bastante típico)
timeit.timeit
o el/usr/bin/time
resultado de cada uno de varios métodos de suma de verificación de un archivo de aprox. 11MB:Por lo tanto, parece que tanto Python como / usr / bin / md5sum tardan unos 30 ms en un archivo de 11 MB. La
md5sum
función relevante (md5sum_read
en la lista anterior) es bastante similar a la de Omnifarious:De acuerdo, estos son de ejecuciones individuales (las
mmap
que siempre son un poco más rápidas cuando se realizan al menos unas pocas docenas de ejecuciones), y la mía generalmente tiene un extraf.read(blocksize)
después de que se agota el búfer, pero es razonablemente repetible y muestra quemd5sum
en la línea de comando está no necesariamente más rápido que una implementación de Python ...EDITAR: Perdón por el largo retraso, no he visto esto en algún tiempo, pero para responder a la pregunta de @ EdRandall, escribiré una implementación de Adler32. Sin embargo, no he ejecutado los puntos de referencia para ello. Básicamente es lo mismo que habría sido el CRC32: en lugar de las llamadas init, update y digest, todo es una
zlib.adler32()
llamada:Tenga en cuenta que esto debe comenzar con la cadena vacía, ya que las sumas de Adler realmente difieren al comenzar desde cero versus su suma para
""
, que es1
- CRC puede comenzar con su0
lugar. losAND
-ing es necesario para convertirlo en un entero sin signo de 32 bits, lo que garantiza que devuelve el mismo valor en todas las versiones de Python.fuente
En Python 3.8+ puedes hacer
Considere usar en
hashlib.blake2b
lugar demd5
(solo reemplacemd5
conblake2b
en el fragmento anterior). Es criptográficamente seguro y más rápido que MD5.fuente
:=
operador es un "operador de asignación" (nuevo en Python 3.8+); le permite asignar valores dentro de una expresión más grande; Más información aquí: docs.python.org/3/whatsnew/3.8.html#assignment-expressionsfuente
Creo que confiar en el paquete invoke y el binario md5sum es un poco más conveniente que el subproceso o el paquete md5
Por supuesto, esto supone que tiene invoke y md5sum instalados.
fuente
path
es una ruta proporcionada por el usuario, esto permitirá que cualquier usuario ejecute comandos bash arbitrarios en su sistema.