En esta entrada intentaré presentar un método bastante común para automatizar el uso de particiones (volúmenes) cifrados. Normalmente al cifrar una partición la configuramos de tal forma que al arrancar el sistema operativo, se pregunte por la contraseña para proceder a descifrar y así poder montarla (utilizarla).
En mi caso tengo una partición en la cual guardo mi información personal. Información que tiene valor para mí y que no me gustaría ver en manos de otras personas (en el hipotético caso que roben en mi casa y se lleven mi pc). Interrumpir la secuencia de arranca para preguntar por la contraseña no me parece una buena idea ya que la mayoría del tiempo no uso esa partición.
Lo ideal sería poder hacer algo fácil y rápido que habilite el uso de dicha partición cuando lo necesito. Sin tener que memorizar una contraseña ya que lo usaré poco y es probable que termine olvidándola. La solución es guardar la llave en una unidad flash usb y condicionarlo de tal forma que al ingresar el usb en la máquina se realice todo el proceso automáticamente.
Lo primero es preparar la partición, en mi caso es /dev/sdb1 y usaré twofish en modo cbc:
cryptsetup -y --cipher twofish-cbc-essiv:sha256 --key-size 256 luksFormat /dev/sdb1
Después de esto procedemos a descifrar la partición para poder usarla:
cryptsetup luksOpen /dev/sdb1 cryptmedia
Y como es la primera vez, debemos agregar el sistema de archivos (ext4 en mi caso) es decir, formatearla:
mkfs.ext4 /dev/mapper/cryptmedia
Ya con esto tenemos nuestra partición lista, en mi caso he escogido /srv/media como el lugar donde la usaré, por lo cual, después de crear dicho directorio, cada vez que quiero usarla tendría que:
cryptsetup luksOpen /dev/sdb1 cryptmedia # (ingresar contraseña) mount /dev/mapper/cryptmedia /srv/media/
Es precisamente esta parte la que queremos automatizar, usando una unidad usb flash. Para lo cual la preparamos de forma similar a esta:
Disk /dev/sdc: 8103 MB, 8103395328 bytes 250 heads, 62 sectors/track, 1021 cylinders, total 15826944 sectors Units = sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disk identifier: 0x2bcfb20c Device Boot Start End Blocks Id System /dev/sdc1 2048 4095 1024 83 Linux /dev/sdc2 4096 15826943 7911424 c W95 FAT32 (LBA)
Es decir, una partición pequeña al comienzo y luego otra para el resto del disco, Creamos los sistemas de archivos:
mkfs.ext4 /dev/sdc1 mkfs.vfat -F32 /dev/sdc2
Procederemos a montar la primera partición del usb (que será la que guardará la llave) y generaremos 256 bytes aleatorios (pseudo aleatorios) que usaremos como nuestra llave, como podrán ver la almacenaré también en formato base64, el cual facilita mucho escribirla (incluso en papel) para almacenarla:
mkdir /tmp/tmp mount /dev/sdc1 /tmp/tmp/ cd /tmp/tmp/ dd if=/dev/random of=key.bin bs=1 count=256 base64 key.bin > key.b64
El fichero key.b64 lo podemos imprimir, copiar, duplicar, etc, esté será nuestra copia de respaldo de la llave, para regresar a la versión utilizable (de ser necesario), usaríamos:
base64 -d key.b64 > key.bin
En este punto tenemos una partición cifrada con una contraseña y una memoria flash usb con otra contraseña mucho más grande (256 bytes). Nos falta asociar la contraseña grande a la partición, crear un script para automatizar el proceso y asegurarnos que dicho script se ejecute automáticamente cada vez que conectamos la memoria usb a la pc.
Agregamos la nueva llave con el siguiente comando:
cryptsetup luksAddKey /dev/sdb1 /tmp/tmp/key.bin # (ingresamos la contraseña anterior)
Es posible ver las llaves que tenemos con:
cryptsetup luksDump /dev/sdb1
Confirmamos que es posible descifrar la partición usando ambas llaves:
cryptsetup luksClose cryptmedia cryptsetup luksOpen /dev/sdb1 cryptmedia # (primera contraseña) cryptsetup luksClose cryptmedia cryptsetup luksOpen --key-file /tmp/tmp/key.bin /dev/sdb1 cryptmedia # (con la contraseña de la memoria usb) cryptsetup luksClose cryptmedia
Ahora sólo falta automatizarlo, para ello crearemos un script que repita los pasos anteriores y usaremos udev para que llamarlo automáticamente cuando se detecte nuestro usb.
Usando el comando lsusb buscamos el id del fabricante y producto, en mi caso:
Bus 009 Device 006: ID 154b:0044 PNY
Lo que interesa es 154b:0044, creamos el fichero /etc/udev/rules.d/100-mount-cryptmedia.rules con lo siguiente:
ACTION=="add", ATTRS{idVendor}=="154b", ATTRS{idProduct}=="0044", SYMLINK+="mediakey%n", RUN+="/usr/local/bin/mount_media.sh"
Es muy importante la parte de SYMLINK, esto no crearé un link simbólico sin importar el número (sdX) que se le asigne, es decir que siempre tendremos un /dev/mediakeyX disponible, en otras palabras:
ls -lh /dev/mediakey* lrwxrwxrwx 1 root root 3 Jan 10 00:00 /dev/mediakey -> sdc lrwxrwxrwx 1 root root 11 Jan 10 00:00 /dev/mediakey0 -> bsg/8:0:0:0 lrwxrwxrwx 1 root root 4 Jan 10 00:00 /dev/mediakey1 -> sdc1 lrwxrwxrwx 1 root root 4 Jan 10 00:00 /dev/mediakey2 -> sdc2 lrwxrwxrwx 1 root root 15 Jan 10 00:00 /dev/mediakey5 -> bus/usb/009/003
En lugar de usar /dev/sdc1 (que puede cambiar) usaremos /dev/mediakey1. Ahora sólo falta crear el script (/usr/local/bin/mount_media.sh) el cual sería algo así:
#!/bin/bash if [ -e /dev/mapper/cryptmedia ]; then exit 0 fi if grep -q cryptmedia /proc/mounts; then exit 0 fi if grep -q tmpmediakey /proc/mounts; then exit 0 fi mkdir -p /tmp/tmpmediakey mount /dev/mediakey1 /tmp/tmpmediakey || exit 1 /sbin/cryptsetup luksOpen --key-file /tmp/tmpmediakey/key.bin /dev/sdb1 cryptmedia umount /tmp/tmpmediakey && rm -rf /tmp/tmpmediakey mount /dev/mapper/cryptmedia /srv/media
Obviamente este script puede ser mejorado mucho más, pero a modo de explicación e intentando mantenerlo lo más simple posible, funciona. Por último sólo nos queda eliminar la primera llave:
cryptsetup luksRemoveKey /dev/sdb1 # (contraseña a eliminar)
Esto nos deja con una sola llave (la de la memoria usb) en nuestro volumen cifrado.