Encrypted File Containers
I recently came across the need to encrypt some files. I am already running with full disk encryption however wanted something portable that could be transferred between hosts and decrypted as needed. Running mainly Linux, the baked in choice is Linux Unified Key Setup (LUKS).
The following setup will end up looking like this diagram
Creating an encrypted container
Create a file
First step is to create a regular file sized to however big you want the container. This can be done many different ways. The truncate
command is nice and easy but a part of coreutils and not guaranteed to be on every system. dd
on the other hand is pretty ubiquitous.
In the examples, we are creating a 1G file.
Using truncate
truncate -s 1G container.img
Using dd
dd if=/dev/urandom of=container.img bs=1M count=1024
Attach to a loopback device
Now that we have our file, we need to attach it to a loop device in order to encrypt it. losetup
is the go to tool for loopback manipulation. The following command will find the first available loopback device and then use that device to attach our file to.
sudo losetup --show -f ./container.img
Take note of the loopback device assigned (printed out) as we will use it in the next step.
losetup -l
Encrypt
With all of the setup done, we can now encrypt. For as complicated as encryption can be, Linux makes things easy with the cryptsetup
command. This one command will let us encrypt / decrypt as well as modify existing encryption schemes on devices. To encrypt our file, we use the following command.
losetup -l
before you run this command as it is destructive.sudo cryptsetup luksFormat /dev/loop0
Opening container
We now have an encrypted file, not much use until we can open it, put a filesystem on it, and store some files. First off, lets open it using the same command we used to encrypt cryptsetup
. The following command will open the container allowing it to be read and written to. This command allows you to specify a string that will become a device mapper entry that we can later reference when running actions on the encrypted partition. In this example, we use “secure”.
sudo cryptsetup open --type luks /dev/loop0 secure
Write a filesystem
With our file open we can put a filesystem on it. Any filesystem will do however if you intend this to be portable, might be a good idea to choose something that is present on most Linux systems. For sake of example, I will be using ext4.
sudo mkfs.ext4 /dev/mapper/secure
Mount and store some files
Final step! Our encrypted container is open, has a filesystem, and now just needs to be mounted. This is done in the typical fashion using the mount
command.
sudo mount /dev/mapper/secure /mnt
A this point, we can add files and write to it at /mnt as if it was a normal part of our file tree.
Closing container
Once done, the device can be unmounted, closed, and detached from the loopback.
sudo umount /mnt
sudo cryptsetup close secure
sudo losetup -d /dev/loop0
Few things to keep in mind to make sure you accidentally loose your data
- Backup your LUKS Header! - If the LUKS header becomes corrupted, all encrypted data will be lost. Backups can be done with
sudo cryptsetup luksHeaderBackup /dev/loop0 --header-backup-file backup.bin
If you ever change your passphrase, be sure to regenerate your backup and delete the old one as access to it and the old passphrase will give access to your data - Take care when updating your passphrase - LUKS allows up to 8 keyslots. Any one of the 8 keys can decrypt the master key which then is used to decrypt the data. If you need to update the passphrase, add it in one of the secondary slots, test that it works, and then remove the old passphrase.