Create an Encrypted Swap File or Device

Everytime you open files, enter passwords, and do things on your computer, data is being opened in RAM. And over time, that data in RAM can get saved to your swap (located on your hard drive) as the system needs more RAM. The issue with this is sensitive information in RAM can make it onto your swap. This data can then be recovered later by those you may not want to have said information.

To prevent this, you can encrypt your swap. There are many ways to do this. We will cover a few here.

As a word of caution, encrypting your swap will not protect it while the system is running. It only protects it when the system is off.

This document assumes you understand command line, creating swaps, mounting of files, and other such things. Note that you could trash your system or make it unbootable. If that’s scary, you probably should read but not do any of the following.

Crypttab

There’s a file called /etc/crypttab that can be used to specify encrypted devices and files that the system is supposed to load up on boot. On systemd systems this is used by systemd-cryptsetup-generator to create unit files to load the devices/files.

The format is fairly simple. There are four columns. From the man page:

The first field contains the name of the resulting encrypted block device; the device is set up within /dev/mapper/.

The second field contains a path to the underlying block device or file, or a specification of a block device via “UUID=” followed by the UUID.

The third field specifies the encryption password. If the field is not present or the password is set to “none” or “-“, the password has to be manually entered during system boot. Otherwise, the field is interpreted as an absolute path to a file containing the encryption password. (Do not use /dev/random).

The fourth field, if present, is a comma-delimited list of options.

Let’s show some examples of how to do this.

With a Set Password

In this example we will create an encrypted swap device that has a password that must be entered on each boot.

Comment out any swap entry(s) in your /etc/fstab file

We need to create the device, which we will use as /dev/sda5.

But before that, fill the device with random data. Otherwise it’s easy to see how much random data is on the drive.

All data will be permenently errased on the drive!

dd if=/dev/urandom of=/dev/sda5 bs=10M

Now, setup the encryption. The prompted password will need to be entered each time the system starts. (See man cryptsetup for other options).

cryptsetup luksFormat /dev/sda5

And then mount it up

cryptsetup luksOpen /dev/sda5 cryptswap

It will create a device at /dev/mapper/cryptswap. Anything written here will be encrypted and save to /dev/sda5 as ecrypted data.

Now we need to format it as a swap.

mkswap /dev/mapper/cryptswap

And now we can run swapon /dev/mapper/cryptswap and we’ll see it’s in the system.

In order to make this happen on system boot, we need to add it to our /etc/crypttab file:

cryptswap  /dev/sda5  none  luks

That tells it to use /dev/sda5 as the source device, that is a luks format, and to save it as /dev/mapper/cryptswap. The none says that it requires a password to be created.

Now, that will create the encryption device. But it won’t load the swap. That’s for fstab. In your /etc/fstab put:

/etc/mapper/cryptswap  none  swap  defaults  0 0

which will do the loading of the swap. And that’s it. Next time you reboot, you’ll be prompted to enter your password for your swap.

With a Random Key

Let’s say we have a server, and we want to have the ability to encrypt the swap, but we don’t want to have to enter in the password each time it boots. To do this, we can either use a keyfile, or have the system create a random key for the swap. The first one is fairly simple, and you can do the same as the above section, substituting in a key for your password (hint: the key option for cryptsetup is --key-file).

But in this example, we will take it one step further and make the swap file make a random key on each boot. That way, what happens on one boot is unknown to the next.

We will use a system that has and LVM setup. If you don’t have that, your can create a single LVM partition on your swap device. The reason for using LVM is so crypttab can easily identify the right location of the device used for the encrypted swap. You see, it’s going to overwrite that partition with the encrypted swap. If it picks your system/data partiton by accedent, then bye bye data. Thus, using something like /dev/sda5 is a bad choice because if the disk’s partitions should change, youd loose a partion of data.

So, in this example we will create an encrypted swap on our lvm /dev/mapper/my_vg-swap, and it will use a different key on each boot.

First, comment out your current swap entry(s) in /etc/fstab.

We don’t need to create the random device, nor the swap. Crypttab will take care of that. You’ll want to fill the partition up with random data to hide how full/empty it is:

This will permenently erase everything on the selected device!

dd if=/dev/urandom of=/dev/mapper/my_vg-swap bs=10M

Once that’s done, put this in your /etc/crypttab file:

cryptswap  /dev/mapper/my_vg-swap  /dev/urandom  swap

And then all we have to do is tell fstab to load it but putting this into /etc/fstab:

/dev/mapper/cryptswap  none  swap  defaults  0 0

And we’re done. Reboot, and you will now have an encrypted swap.

CryptSwap Script

This is an old script of mine that will create an encrypted swap file using a random key. As such, it only lasts the current boot,and each time the computer boots the swap will be encrypted with a new key. It uses cryptsetup and keys are generated in memory and then erased. It seems fairly secure, but that’s relative (as always).

It was made due to the previous limitations of /etc/crypttab of not being able to handle a swap file. The crypttab on most systems is now able to do this with swap files, but it is kept here for old time’s sake.

This script does not allow for hibernating of a computer.

To use, copy the following script and place it in /usr/local/bin/cryptsetup (or somewhere else if you prefer). Make it executable (chmod +x /usr/local/bin/cryptsetup).

Run by adding to your /etc/rc.local file, or another such file that runs at startup.

/usr/local/bin/cryptsetup on

Like swapon and swapoff, and it will automatically start (on) or stop (off) the encrypted swap.

It does not support multiple swap files. You can save multiple copies of it for that, editing each one to use a different swap file, or modify it with a “for EACH in $FILES.”

#!/bin/bash

if [ $UID -ne 0 ] ; then
  echo "You must be root to do that!"
  exit 1
fi

PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin

SWAPFILE=/swapfile
SWAPNAME=enc_swap_area

DEBUG=0
[ "$2" == "-d" ] && DEBUG=1
echo_debug() {
  [ $DEBUG -eq 1 ] && echo " -$*"
}

case $1 in
  'on') 
        # check if it is already mounted
        if [ -e /dev/mapper/$SWAPNAME ] ; then
          echo "Encrypted swap appears to already be active. Try 'cryptsetup off'"
          exit
        fi
        
        # set temp file
        if [ $(mount | grep -c /dev/shm) -eq 1 ] ; then
          SWAPKEY=$(mktemp -p /dev/shm swapfile.key.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX)
        else
          SWAPKEY=$(mktemp -p /tmp swapfile.key.XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX)
        fi
        
        # gen key
        echo_debug "Generating key to $SWAPKEY"
        rm -f "$SWAPKEY"
        dd if=/dev/urandom of="$SWAPKEY" count=4096 bs=1
        #shred "$SWAPPUB"
              
        # mount file to loopback
        SWAPLOOP=$(losetup -a | grep "($SWAPFILE)" | cut -f1 -d':')
        if [ -z "$SWAPLOOP" ] ; then
          echo_debug "Mounting file to loopback"
          losetup -f $SWAPFILE
          SWAPLOOP=$(losetup -a | grep "($SWAPFILE)" | cut -f1 -d':')
        else
          echo_debug "File was already mounted on loopback"
        fi
        echo_debug "Mounted $SWAPFILE to $SWAPLOOP"
        
        #cryptsetup
        echo_debug "Creating ecrypted area"
        cryptsetup luksFormat -q --cipher "aes-cbc-essiv:sha256" "$SWAPLOOP" "$SWAPKEY" \
          > /dev/null 2> /dev/null
        echo_debug "Opening encrypted area"
        cryptsetup luksOpen --key-file "$SWAPKEY" "$SWAPLOOP" "$SWAPNAME" \
          > /dev/null 2> /dev/null
        if [ -e /dev/mapper/$SWAPNAME ] ; then
        	echo_debug "Making swap"
        	mkswap -L "$SWAPNAME" /dev/mapper/$SWAPNAME > /dev/null
        	echo_debug "Turing swap on"
        	swapon /dev/mapper/$SWAPNAME
        else
         	echo "Mounting of file FAILED"
        fi
        echo_debug "Cleaning up"
        shred  "$SWAPKEY"
        shred -zu "$SWAPKEY"
        rm -f "$SWAPKEY" 
        echo_debug "Done"
        ;;
   
   'off')
        # umount swap
        if [ -e /dev/mapper/$SWAPNAME ] ; then
          echo_debug "Turning off swap"
          swapoff /dev/mapper/$SWAPNAME
          if [ $! -ne 0 ] ; then
            echo "Swap cannot be turned off. Try freeing some RAM."
            exit
          fi
          echo_debug "Closing encrypted area"
          cryptsetup luksClose $SWAPNAME
        fi
        SWAPLOOP=$(losetup -a | grep "($SWAPFILE)" | cut -f1 -d':')
        if [ -n "$SWAPLOOP" ] ; then
          echo_debug "Removing file from loopback"
          losetup -d "$SWAPLOOP"
        fi
        echo_debug "Done"
        ;;

   *)
        echo "Usage: cryptswap `<on off>` [-d]"
        exit
        ;;
        
esac