Introducción

Hace poco tuve la necesidad de copiar el contenido de una partición a otra; se trataba de documentos, por lo que necesitaba verificar que la copia fuera correcta. Yo sabía que existe el programa md5sum, pero no lograba hacerlo andar recursivamente, dado que no trae esta opción. Navegando, me topé con este foro donde daban la respuesta de cómo hacer un chequeo md5 de manera recursiva.
Entonces, me decidí a crear un script, el cual comparto aquí.

>> Ver este post en Taringa! <<

Descripción

Este script tiene doble función: por un lado crea recursivamente los hashes md5 de todos los archivos de un determinado directorio, y los guarda en un archivo de texto; por otro lado, es capaz de leer dicho archivo para luego realizar la verificación.
¿De qué se trata? Pues de tener la capacidad de verificar una enorme cantidad de archivos; puede verificarse que la copia fue correcta con facilidad, y detectar si algún archivo falló.

ACTUALIZACIÓN: Gracias Tim7967 por aclarar que MD5 ya se ha probado vulnerable contra distintos ataques, y no puede ser usado con fines criptográficos.  Sin embargo, al ser un algoritmo implementado en cualquier linux, y ser muy veloz, sirve a los fines de realizar la verificación de archivos, dado que las probabilidades que se produzca una colisión entre dos o más archivos en una pc, son prácticamente nulas.  Pero si ustedes requieren de un algoritmo de alta seguridad, como Tim7967 nos cuenta, deberían pensar en SHA-2.  Más información abajo, en los comentarios.

ACTUALIZACIÓN: Gracias a un tip de vocin pongo aquí el código utilizando el comando code

Simplemente deben copiar desde el inicio hasta el final del script, pegarlo en un archivo de texto plano y vacío (gedit, leafpad, vim, nano, etc), guardarlo y darle permiso de ejecucion: chmod +x md5recursivesum ( el nombre que le hayan dado).

#!/bin/bash

#------------------------------------------------------------------------
# Script para crear y verificar hashes md5
# CopyLeft HacKan @ HacKan & CuBa co. 2010, 2011, 2012
# http://www.hackan.com.ar
#
# 	|  Este script se entrega 'tal cual' y como Open Source,
# 	| y como tal puede modificarse, adaptarse y usarse libremente.
#  	|  Favor de mantener autores, coautores y demás info intacta,
#	| añadiendo la suya si así lo desea.
#
# Si realiza alguna mejora, me gustaría saber de ello :)
#
# Para 'instalar' este script, es decir, ejecutarlo como un comando
#	desde cualquier lugar del sistema, copiarlo a la carpeta
#	/usr/bin.
# P.E.: sudo cp ~/Escritorio/md5recursivesum /usr/bin/md5rsum
# Personalmente, le acorte el nombre a md5rsum, por comodidad
#
# Requerimientos
# ===============
#
# Este script hace uso de los siguientes programas:
# md5sum
# notify-send, del paquete notify-osd
#------------------------------------------------------------------------

#------------------------------------------------------------------------
# Registro de cambios
#=====================
#
# v1.1
# - Corregido: salir con estado 0 en modo verificacion aun cuando
#	haya ocurrido un error.
#
# v1.0
# - Agregado grep en verificacion: permite mostrar solo los archivos
#	correctos o solo los incorrectos, o todos.
# - Editada la ayuda acorde
# - Se agregó modo silencioso: no muestra mensajes con notify-send
#
# v0.9
# - Se modificó acción cuando no se especifica archivo
#	en el modo verificación
# - Se agregó segundo argumento para el modo crear, que especifica
#	la ruta y/o nombre de archivo donde guardar el archivo
#	de verificación
# - Se modificó la ayuda
# - En el modo crear, se cambió forma de trabajar: primero
#	se crea un archivo temporal, y finalmente se copia a
#	destino y se elimina el temporal
# - Se modificó rutina de verificación, para chequear primero que
#	el archivo exista
# - Se agregaron opciones a la configuración interna
#
# v0.8
# - Algunos cambios en la sintaxis para mejor lectura y optimización
#
# v0.7
# - Se le agrega notify-send para notificar finalización del proceso
# - Se agregan etiquetas para separar el script en secciones: config,
#	funciones y script.
# - Se agrega disclaimer
#
# v0.6
# - Primera versión funcional
#------------------------------------------------------------------------

#------------------------------------------------------------------------
# Para hacer...
# ====================
#
# - Traducir a inglés
#------------------------------------------------------------------------

#--------- Config ---------#
title="md5recursivesum"
version="1.0"
crear="-c"
qcrear="${crear}q"	# Debe empezar con los caracts. del modo crear
verif="-v"
qverif="${verif}q"	# Debe empezar con los caracts. del modo verif
grepOK="-gok"
grepKO="-gko"
ayuda="--help"
iconOK="/usr/share/icons/Humanity/actions/48/dialog-apply.svg"
iconKO="/usr/share/icons/Humanity/actions/48/process-stop.svg"
iconSTART="/usr/share/icons/Humanity/actions/48/system-run.svg"
md5fname="md5sum.md5"
tmpdir="/tmp"
#--------------------------#

#-------- Funciones -------#
function fin {
	echo
	echo "Script finalizado"
	exit $1
}

function f_ayuda {
	echo "Crea o verifica un archivo de hash md5.  A diferencia de md5sum, permite crear un archivo md5 conteniendo el hash de multiples archivos.  Puede procesar directorios recursivamente.  Hace uso de md5sum y notify-osd, por lo que requiere de los mismos."
	echo
	echo "Modo de uso: ${title} ([${crear} | ${qcrear}] | [${verif} | ${qverif}] | ${ayuda}) ([DIRECTORIO] | ARCHIVO) [/RUTA/ARCHIVO.MD5 | [${grepOK} | ${grepKO}]]"
	echo
	echo "	${crear}	Modo creacion.  Crea un archivo hash md5"
	echo "	${qcrear}	Modo creacion silencioso: no muestra mensajes via notify-osd"
	echo
	echo "	${verif}	Modo verificacion.  Lee un archivo md5 y verifica los archivos correspondientes"
	echo "	${qverif}	Modo verificacion silencioso: no muestra mensajes via notify-osd"
	echo "	${grepOK}	En el modo verificacion: solo muestra los archivos correctos"
	echo "	${grepKO}	En el modo verificacion: solo muestra los archivos incorrectos"
	echo
	echo "	${ayuda}	Muestra esta ayuda"
	echo
	echo
	echo "	Modo creacion"
	echo "1- Para crear el hash de los archivos de un directorio recursivamente: $title $crear /directorio/a/chequear"
	echo "P.E.: $title $crear /home/usuario/Documentos"
	echo "Por defecto, el archivo de verificación será creado en el directorio actual, bajo el nombre ${md5fname}"
	echo
	echo "1.1- Se puede especificar la ruta para guardar el archivo de verificacion en un tercer argumento.  ¡La misma debe ser absoluta, y NO terminar con '/'!"
	echo "P.E.: $title $crear /home/usuario/Documentos /home/usuario"
	echo "Esto guardara el archivo md5sum.md5 en el directorio /home/usuario"
	echo
	echo "1.2- También se puede especificar un nombre de archivo, con o sin la ruta.  Si no especifica ruta, se considera el directorio actual"
	echo "P.E.: $title $crear /home/usuario/Documentos /home/usuario/docs.md5"
	echo "P.E.: $title $crear /home/usuario/Documentos docs.md5"
	echo
	echo
	echo "	Modo verificacion "
	echo "2- Para verificar los archivos con un archivo de hash: $title $verif /ruta/del/archivo.md5"
	echo "P.E.: $title $verif ./${md5fname}"
	echo "Si no se especifica ruta del archivo, se buscara el archivo en el directorio actual"
	echo
	echo "2.1- Para mostrar solo los archivos correctos, emplee el parámetro ${grepOK}"
	echo "P.E.: $title $verif ./${md5fname} ${grepOK}"
	echo
	echo "2.2- Para mostrar solo los archivos incorrectos, emplee el parámetro ${grepKO}"
	echo "P.E.: $title $verif ./${md5fname} ${grepKO}"
	echo
	echo
	echo "Esta ayuda se muestra con el parametro \"$ayuda\" o bien si no se le pasan parametros al script"
}

function notify {
	# Debe recibir el path al ícono primero, y el texto segundo.
	# Si es modo quiet, no usar notify-send
	if [ ${param1} != ${qcrear} ] && [ ${param1} != ${qverif} ]; then
		notify-send -i "${1}" "${title}" "${2}"
	fi
	if [ ${1} = ${iconKO} ]; then
		echo -n "ERROR: "
	fi
	echo ${2}
}
#--------------------------#

#--------- Script ---------#
echo "-----------------------------------------------"
echo "$title v$version by HacKan & CuBa co. 2010"
echo "          http://www.hackan.com.ar"
echo "-----------------------------------------------"
echo

# Modo
param1=${1}

# Ruta para crear archivo (-c) o archivo a verificar (-v)
param2=${2}

# Destino para almacenar archivo (-c) o modo grep (-v)
param3=${3}
md5f=${param3}

if [ -z ${param1} ] || [ ${param1} = $ayuda ]; then
	f_ayuda
	fin 0
fi
ECODE=0

# Tomo del primer argumento, la cant de caracteres que tiene el modo
if [ ${param1:0:${#crear}} = $crear ]; then
	# Crear archivo md5
	if [ -d ${param2} ]; then
		if [ -z ${param2} ]; then
			echo "No se indico directorio, se procesara el actual"
			param2="./"
		fi
		if [ -z ${param3} ]; then
			# Si no se especifica ruta para guardar
			#	archivo md5, se usa la actual
			param3=${param2}
		fi
		if [ -d ${param3} ]; then
			# Es un directorio, no un archivo
			md5f="${param3}/${md5fname}"
		fi
		notify ${iconSTART} "Creando hash md5 para los archivos dentro de ${param2}"
		echo "Espere por favor..."
		rm -f "${tmpdir}/${md5fname}"
		find ${param2} -type f -print0 | xargs -0 md5sum >> "${tmpdir}/${md5fname}"
		cp "${tmpdir}/${md5fname}" "${md5f}"
		if [ $? -ne 0 ]; then
			# Error en la copia
			notify ${iconKO} "Se ha producido un error al copiar el archivo ${tmpdir}/${md5fname} a ${md5f}"
			fin 1
		fi
		rm -f "${tmpdir}/${md5fname}"
		notify ${iconOK} "Archivo guardado como ${md5f}"
	else
		notify ${iconKO} "No existe el directorio ${param2}"
		ECODE=1
	fi
else
	if [ ${param1:0:${#verif}} = $verif ]; then
		# Verificar directorio con archivo .md5
		if [ -z ${param2} ]; then
			echo "No se indico ruta del archivo, se usara la actual"
			param2="./${md5fname}"
		fi
		if [ ! -e ${param2} ]; then
			notify ${iconKO} "No existe el archivo ${param2}; no se puede realizar la verificacion"
			fin 1
		fi
		notify ${iconSTART} "Verificando archivos en base a ${param2}... Espere por favor..."
		echo
		# Verifico archivos
		md5sum -c ${param2} > "${tmpdir}/md5sum.out"
		resultado=$?
		# Imprimo resultado como corresponda
		# Si el tercer argumento viene vacío, le pongo un texto cualquiera
		#	para que bash no se queje al hacer la comparación con un
		#	string en los próximos if's.
		if [ -z ${param3} ]; then param3="vacio"; fi
		if [ ${param3} = ${grepOK} ]; then
			cat "${tmpdir}/md5sum.out" | grep "suma coincide"
		elif [ ${param3} = ${grepKO} ]; then
			cat "${tmpdir}/md5sum.out" | grep "no coincide"
		else
			cat "${tmpdir}/md5sum.out"
		fi
		# Elimino temporal
		rm "${tmpdir}/md5sum.out"
		echo
		if [ ${resultado} -eq 0 ]; then
			notify ${iconOK} "Todos los archivos fueron verificados satisfactoriamente"
		else
			notify ${iconKO} "Al menos un archivo fallo en la verificacion"
		fi
		ECODE=${resultado}
	else
		notify ${iconKO} "Opcion invalida: ${param1}.  Utilice \"$title $ayuda\" para ver la ayuda"
		ECODE=1
	fi
fi
fin ${ECODE}
#--------------------------#

Ultima versión: 1.1

md5recursivesum.zip – MD5 Hash: 93c9d378af122a03e46caac74e49331d
(Firmado por hackan@hackan.com.ar [ID 0x636A37C0]: md5recursivesum-v1.1.zip.sig)
¿qué significa esto?

Otras versiones

v1.1: md5recursivesum-v1.1 – MD5 Hash: 93c9d378af122a03e46caac74e49331d
v1.0: md5recursivesum-v1.0 – MD5 Hash: eeb76267f9a477b45aeada069d7598b4
v0.9: md5recursivesum-v0.9 – MD5 Hash: 7f2514aeca5fff29d06e68719514b4fe
v0.8: md5recursivesum-v0.8 – MD5 Hash: afd29316c175ca4e0c8b531abaf25a2a

¿De qué se trata esto del chequeo con hashes md5?

MD5 es uno de los algoritmos de reducción criptográficos diseñados por el profesor Ronald Rivest del MIT (Massachusetts Institute of Technology, Instituto Tecnológico de Massachusetts).

La codificación del MD5 de 128 bits es representada típicamente como un número de 32 dígitos hexadecimal. El siguiente código de 28 bytes ASCII será tratado con MD5 y veremos su correspondiente hash de salida:

MD5<”Esto sí es una prueba de MD5″> = e99008846853ff3b725c27315e469fbc

Un simple cambio en el mensaje nos da un cambio total en la codificación hash, en este caso cambiamos dos letras, el «sí» por un «no».

MD5<”Esto no es una prueba de MD5″> = dd21d99a468f3bb52a136ef5beef5034

Otro ejemplo serí­a la codificación de un campo vací­o:

MD5<”"> = d41d8cd98f00b204e9800998ecf8427e

¿De qué nos sirve todo eso? Pues muy simple: el md5 permite crear un hash (un código, digamos) que es único para cada archivo; de esta manera, si p.e. copiamos un archivo, podemos verificar si la copia fue correcta o no creando el hash de cada uno y luego comparándolos: si son iguales es que la copia fue correcta; caso contrario, la misma falló.
El algoritmo es muy veloz, y muy eficiente.

Este script nos facilita realizar esta clase de comprobaciones, sin que tengamos necesidad de saber siquiera qué es md5.

Modo de uso

El modo de uso es bastante simple. El script se ejecuta en la consola, no posee interfaz gráfica; y NO requiere ser root (es decir, NO debe ejecutarse con sudo), a excepción de que los archivos o el directorio a verificar solo pueda ser accedido por el root.

Se ejecuta como cualquier otro script, yendo a su carpeta y poniendo: ./md5recursivesum
Si quieren pueden hacer lo sig. para poder ejecutarlo desde cualquier lado (sin tener q ir al directorio) como si fuera un comando más: sudo ln -t /usr/bin /ruta/al/script/md5recursivesum
Esto crea un link al script en la carpeta /usr/bin. Si desean que esté disponible para todos los usuarios, pueden considerar copiar el script a la carpeta /usr/bin en lugar de poner un link (acceso directo, quiero decir).

1- Para crear el hash de los archivos de un directorio recursivamente: md5recursivesum -c /directorio/a/chequear
P.E.: md5recursivesum -c /home/usuario/Documentos

Esto creará un archivo llamado md5recursivesum.md5 en el directorio actual desde donde ejecutamos el script, cuyo contenido será la ruta y nombre de cada archivo, con su respectivo hash.

2- Para verificar los archivos con un archivo de hash: md5recursivesum -v /ruta/del/archivo.md5
P.E.: md5recursivesum -v ./md5sum.md5

Este modo verifica cada archivo con el hash que encuentra en el archivo de hashes (en el ejemplo, llamado md5sum.md5)
Se puede emplear ‘ | grep “suma coincide”‘ para mostrar solo los correctos y ‘ | grep “no coincide”‘ para solo los incorrectos.
P.E.: md5recursivesum -v ./md5sum.md5 | grep “suma coincide”
Esto mostrará solamente los archivos cuya comprobación resulto correcta.

En la versión 1.0 se agregan los parámetros -gok y -gko para mostrar solo los resultados válidos o solo los inválidos respectivamente, usando grep (esto evita tener que hacer lo antedicho)

Esta ayuda está incorporada al script: md5recursivesum –help

Fuentes

> http://www.linuxquestions.org/questions/linux-software-2/how-to-create-md5sum-for-a-directory-689242/
De allí saqué la forma de realizar el chequeo recursivo.

> http://www.linuxconfig.org/Bash_scripting_Tutorial
Allí aprendí a escribir scripts en bash. Es realmente simple, similar al batch de Winbugs, pero muchísimo más potente.

> http://es.wikipedia.org/wiki/MD5
Info sobre MD5.

Palabras finales

Pueden distribuir y/o modificar el script a gusto y piacere, es open source ;)
Lo que les pido es que me mencionen en el mismo.
Se aceptan sugerencias, corrección de bugs, etc.

Espero que les sea útil. Sin más, me despido.

¡Saludos!

Fue otra creación de HacKan & CuBa co.

HacKan & CuBa co. CopyLeft 2010.

Otros posts que podrían interesarte

  2 Responses to “[Bash Script] Realizar chequeo MD5 recursivamente”

  1. Although if you just found out about MD5, and are really interested in using it to check file security to see if something has been modified, MD5 has been proven to be vulnerable to have collision vulnerabilities, theoretically vulnerable to Preimage Vulnerabilities, and if you are not careful with the salt hashes you use, it is also vulnerable to rainbow tables.

    If you are looking for a integrity checking algorithm for security which needs to be secure, I’d recommend the SHA-2 series of hashes (SHA-224, SHA-256, SHA-384, SHA-512). MS5 can still be trusted for most common operations, but if you want to be absolutely secure, you may want to use something else.

    Thought I’d point this out for anybody new to file integrity checking.

  2. Of course, MD5 can ONLY be used to check non-security file integrity. YOU CAN’T IMPLEMENT IT as a cryptographic hashing function, ’cause as you said, it’s know to be week with the so-called birthday attack. However, there are ways to secure it, like using random salt, like WP does to store passwords.
    But in this case, MD5 comes integrated with every linux, and is one of the fastest algorithms to check for file integriry, which is why is still in use. You won’t likely have a collision attack with your own files, the possibilities are practically null. And even if you do, you might only have with 2 files, no chances at all of having more files collisioning.
    You made a really good point, because i see i forget to talk about it :D

 Leave a Reply

(necesario)

(necesario)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

   
© 2006, 2007, 2008, 2009, 2010, 2011 HacKan & CuBa co. Suffusion theme by Sayontan Sinha