Encrypted Containers Without TrueCrypt

E

Eric Hansen

Guest
A lot of people use TrueCrypt to create virtual drives/containers to encrypt files, and it works wonders when you’re using Windows, because Windows has no built-in support for such technology. However, in the world of Linux, we’ve been fortunate to have this for a vast amount of time! :D

This will be a small article (the next one will cover other ways to use cryptsetup), but beneficial nonetheless.

You can do this with a regular device, but we’ll use our system’s resources for this. By this I mean we will convert a file to a block device (drive), and treat that as the container. I’m doing this on Ubuntu 12.04 stock kernel (most come with dm-crypt and LUKS support enabled by default now anyways).

Also, sudo su - so you can be root for this, makes it easier in the end and most of the commands will require it anyways for this guide.
Creating The Block Device

This is going to be semi-long compared to the rest because there’s two parts to it. First, we need to create an empty file of a specific size and null/zero it out. Then we need to connect it to our system so it thinks its a block device. After that the rest is pretty simple, but I’ll break this into smaller parts as well.
Installing Needed Software

While the kernel itself typically supports the methods used by default, we fall back into the issue again (similar to LXC) where we need to have userspace tools. Assuming you’re using Debian/Ubuntu (and this is the only time I’ll make this assumption throughout this entire guide), simply install (as root) cryptsetup:
Code:
apt-get install cryptsetup
Creating the File

Typically when you create a file in Linux there’s a multitude of ways to do it (echo to it, touch, editors, etc…). However, given the nature of what this file will be used for none of those methods will work for us. We need a file that’s pre-allocated to a specific size and yet empty.

For us, we have a very useful (and standard) tool called dd. What this does for us is everything stated above. We’ll pass it 3 arguments: input file, output file and count size (how big we want it to be). The input file will be /dev/zero so we can zero it out, the output file will be /root/test.bin but you can name it and place it wherever you want, and we’ll make it 512MB big. Now, since I believe drives should be measured in 1024-bytes, not the 1000-bytes you often see, we’ll make the conversion as such too:
Code:
dd if=/dev/zero of=/root/test.bin count=1000k
After a little bit (depending on how fast your computer, I/O, etc… is), you’ll see output like this:
Code:
root:~# dd if=/dev/zero of=~/test.bin count=1000k
1024000+0 records in
1024000+0 records out
524288000 bytes (524 MB) copied, 2.62044 s, 200 MB/s

Its basically telling you some data about the disk performance (irrelevant here but its common to see this when people are testing the performance of VPSes).
Connecting a Device to the File

We have the file, but how are we going to trick our system into thinking that its a device? Well, a small bit of technical detail: devices in Linux are nothing but special files.

That’s right. When you mount a drive, the kernel/system just sees it as another file (specifically a directory). So how are we going to make this work in our favor? Well, in terms of networking there’s always a loopback device (127.0.0.1 typically). This is nothing but a dummy adapter on the system. The same exists for block devices, and by default you’ll probably have more than one of them. As a demonstration:
Code:
root:~# ls -liha /dev/loop*
7196 brw-rw---- 1 root disk  7,  0 Aug 22 15:28 /dev/loop0
7197 brw-rw---- 1 root disk  7,  1 Aug 22 09:33 /dev/loop1
7198 brw-rw---- 1 root disk  7,  2 Aug 22 09:33 /dev/loop2
7199 brw-rw---- 1 root disk  7,  3 Aug 22 09:33 /dev/loop3
7200 brw-rw---- 1 root disk  7,  4 Aug 22 09:33 /dev/loop4
7201 brw-rw---- 1 root disk  7,  5 Aug 22 09:33 /dev/loop5
7202 brw-rw---- 1 root disk  7,  6 Aug 22 09:33 /dev/loop6
7203 brw-rw---- 1 root disk  7,  7 Aug 22 09:33 /dev/loop7
7195 crw------- 1 root root 10, 237 Aug 22 09:33 /dev/loop-control

Ignore the last one, but the 0-7 entries above are what we’re interested in. These are the loopback devices of blocks, which we can use to our advantage. There’s more to these which I’ll show at the end, but essentially we just need to pick an unused loop device we want to use, and point it to our newly created file (basically like mount), using losetup:
Code:
losetup /dev/loop0 /root/test.bin
I had to use loop1 but that’s irrelevant. You won’t see any output saying it was successful, otherwise you’ll see some error stating why it wouldn’t work. Essentially it creates what can be considered a symlink of test.bin to loop0.
Partition It

Descriptive header, eh?

So now we have to format our file/device so our system can work with it. I usually use cfdisk but for the sake of this article we’ll use fdisk:
Code:
root:~# fdisk /dev/loop0
Device contains neither a valid DOS partition table, nor Sun, SGI or OSF disklabel
Building a new DOS disklabel with disk identifier 0x20ce46d0.
Changes will remain in memory only, until you decide to write them.
After that, of course, the previous content won't be recoverable.

Warning: invalid flag 0x0000 of partition table 4 will be corrected by w(rite)

Command (m for help): n
Partition type:
  p  primary (0 primary, 0 extended, 4 free)
  e  extended
Select (default p): p
Partition number (1-4, default 1):
Using default value 1
First sector (2048-1023999, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-1023999, default 1023999):
Using default value 1023999

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: Re-reading the partition table failed with error 22: Invalid argument.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.

I’m not sure if multiple partitions can be made safely, I’ve tried but had limited success, so we’ll just stick with one for now.
Setting Up dm-crypt and LUKS

Setting Up Crypt

Normally this would be the step you format the partition, right? Well, lets not and say we will later. Instead we’ll make it a container first, partition it second. Now, there’s a few options available to you at this stage, but to get our feet wet and make sure things work we’ll do virtually the bare minimum:
Code:
root:~# cryptsetup --verbose --verify-passphrase luksFormat /dev/loop0

WARNING!
========
This will overwrite data on /dev/loop0 irrevocably.

Are you sure? (Type uppercase yes): YES
Enter LUKS passphrase:
Verify passphrase:
Command successful.

The “--verbose” switch allows cryptsetup to give us more information, while “--verify-passphrase” makes us type it in twice so we know there’s no goofs. “luksFormat” specifies that we want to use the LUKS extension of dm-crypt and also tells dm-crypt to create a LUKS header on /dev/loop0. It’ll ask you for a passphrase which is the password needed to actually mount it. Multiple passphrases can be provided as well, but we’ll stick with one for now.

There’s really not a whole lot to this exactly so that’s why I didn’t go into detail about this.
Opening the Block Device

In order for our system to see it (and for us to format it), we need to connect the block device to our system. Fortunately cryptsetup has an easy-to-do way of this, mapping our block device to /dev/mapper/*. Let me explain:
Code:
root:~# cryptsetup luksOpen /dev/loop0 sometest
Enter passphrase for /dev/loop0:

We have /dev/loop0 (the block device) mapped to our test.bin file so we’re going to stick working with block files pretty much forever now in this. But what we do is tell cryptsetup to mount the container to /dev/mapper/sometest (the last parameter passed is what we’re mapping to). So for example if you have /dev/sda1 mapped to /, this mapped /dev/loop0 to /dev/mapper/sometest, where you can store all of your files.

But wait, there’s one issue...its not formatted!
Formatting Our Container

Remember that partition we made? That’s why we made it. All of our data will fit inside of that partition. To do that though we need to create a filesystem on it (right now its like a bowl of tofu, lets make it pudding!):
Code:
root:~# mkfs.ext4 -j /dev/mapper/sometest
mke2fs 1.42 (29-Nov-2011)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
Stride=0 blocks, Stripe width=0 blocks
127512 inodes, 509952 blocks
25497 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67633152
63 block groups
8192 blocks per group, 8192 fragments per group
2024 inodes per group
Superblock backups stored on blocks:
    8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409

Allocating group tables: done                         
Writing inode tables: done                         
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done
Simple, right? Now the rest is normal procedure.
Mounting the Container

So, now that we have this wonderfully encrypted container for storage, how do we mount it? Well, lets first create a folder to mount it to (remember, we’re still working with block devices at this point):
Code:
mkdir /mnt/encrypto
Then, so we can see it:
Code:
mount /dev/mapper/sometest /mnt/encrypto
Voila! Now when you put files into there it’ll be mapped to the container that encrypts everything thanks to LUKS and dm-crypt! To unmount you just do an umount on it.
 

Attachments

  • slide.jpg
    slide.jpg
    26.6 KB · Views: 55,318
Last edited:


I'm not sure why you feel the need to start a good post on Linux file/disk encryption with some misinformed comment about Windows, but that does seem to be a common theme in the Linux world, and unfortunately it's not one that wins Linux any respect or followers. I like Linux for several reasons - openness, collaboration, and no licensing hassles, but Windows has its market share for some solid reasons - backwards compatibility, reliability, corporate tooling, developer tools, and hardware support. To be honest, I have a love-hate relationship with both Windows and Linux - they both have their strengths and weaknesses.

In the interest of dispelling some FUD, you may want to try the following command-line to enable full-disk encryption on a recent version of Windows:

Code:
PS C:\> $SecureString = ConvertTo-SecureString "1234" -AsPlainText -Force 
PS C:\> Enable-BitLocker -MountPoint "C:" -EncryptionMethod Aes256 -Pin $SecureString -TPMandPinProtector
Source: Microsoft Technet (sorry can't post link here due to forum rules)

If you want to encrypt the files in a folder, use the following:

Code:
PS C:\> cipher /e C:\SomeImportantData
Source: ciper /?

Don't forget to run these commands as administrator (in Windows, root => the user called Administrator and sudoers => member of the administrators group).

What Windows doesn't have out-of-the-box support for without installing TrueCrypt is encrypted containers, although I'm not really sure how installing TrueCrypt is any different to installing the encryption tools you used (apt-get install cryptsetup). It is possible to mount virtual drives (i.e. vhd files) under Windows, so it may be possible to apply full disk encryption to a container in a similar way to what you did in your post. I haven't tried it, though, since TrueCrypt is a good cross-platform solution to the problem.
 
I'm not sure why you feel the need to start a good post on Linux file/disk encryption with some misinformed comment about Windows, but that does seem to be a common theme in the Linux world, and unfortunately it's not one that wins Linux any respect or followers. I like Linux for several reasons - openness, collaboration, and no licensing hassles, but Windows has its market share for some solid reasons - backwards compatibility, reliability, corporate tooling, developer tools, and hardware support. To be honest, I have a love-hate relationship with both Windows and Linux - they both have their strengths and weaknesses.

In the interest of dispelling some FUD, you may want to try the following command-line to enable full-disk encryption on a recent version of Windows:

Code:
PS C:\> $SecureString = ConvertTo-SecureString "1234" -AsPlainText -Force
PS C:\> Enable-BitLocker -MountPoint "C:" -EncryptionMethod Aes256 -Pin $SecureString -TPMandPinProtector
Source: Microsoft Technet (sorry can't post link here due to forum rules)

If you want to encrypt the files in a folder, use the following:

Code:
PS C:\> cipher /e C:\SomeImportantData
Source: ciper /?

Don't forget to run these commands as administrator (in Windows, root => the user called Administrator and sudoers => member of the administrators group).

What Windows doesn't have out-of-the-box support for without installing TrueCrypt is encrypted containers, although I'm not really sure how installing TrueCrypt is any different to installing the encryption tools you used (apt-get install cryptsetup). It is possible to mount virtual drives (i.e. vhd files) under Windows, so it may be possible to apply full disk encryption to a container in a similar way to what you did in your post. I haven't tried it, though, since TrueCrypt is a good cross-platform solution to the problem.
While I don't discredit your examples of PowerShell, and you're right in that I was wrong, here's why I disagree with providing the example why I don't see a reason to make a note of it:

Windows is primarily meant for people who want a system up and running. Such people usually aren't power users (not saying all aren't). As such, said people may not be aware of Power Shell at all. I didn't know Windows had anything like it until I was messing around at my university and a teacher asked me to teach it.

Also, even though Windows can mount VHD files, that doesn't equate to actual cryptographical containers. That equates to Windows knowing the format and specs of a VHD file. That alone should raise a red flag if you're considering using a VHD file as a replacement to a TrueCrypt container. Windows is a highly targeted OS and most of its issues seem to be part of the Windows core itself. If the core knows how to access a VHD file without any dependencies then what is to say someone who exploits a part of the Windows code can't gain access to anything on the VHD file as well?

I'm not bashing Windows. I love it and dual-boot with it, just as I love Linux and dual-boot with it as well. But you can't really compare a VHD file to a TrueCrypt container as if they can be interchangable.
 
You're right that Windows has a wider range of users - from "power users" through to people who just want to check their emails. I would love to be able to install Linux on my mum's PC, and had a go on my wife's with dire consequences and at great risk to my marriage :) She's running Windows 8 now.

I am assuming that mounting a VHD means that it is possible to add full-disk encryption to the contents of that VHD, although I may be wrong. The way I read your blog, this appears to be what you did in Linux as well i.e. create a virtual disk, partition it and then encrypt the partition?

Nice blog entry - I learned a few things from it. Well explained with a good level of detail and explanations. I'll have to do a bit more research on loopback devices, since that concept is a bit foreign to me.
 
I am assuming that mounting a VHD means that it is possible to add full-disk encryption to the contents of that VHD, although I may be wrong. The way I read your blog, this appears to be what you did in Linux as well i.e. create a virtual disk, partition it and then encrypt the partition?

I haven't mounted a VHD before in Windows so my knowledge of what you can do with it is pretty minimal, but if its like mounting anything else then no, you can't do full-disk encryption. Reason being you would have to install TrueCrypt's special boot loader so the drive can be decrypted. At least enough to boot.

Full-disk encryption is possible in a VHD but you would have to boot it up with through your virtual machine app (VMware, VBox, etc...) first.

What I did in Linux with this is basically take what TrueCrypt does with a lot of operating systems (create a specialized file that encrypts data) and target it towards more *nix-specific.

Nice blog entry - I learned a few things from it. Well explained with a good level of detail and explanations. I'll have to do a bit more research on loopback devices, since that concept is a bit foreign to me.
Thank you. I do try but if its a big text guide I tend to break them up into parts.
 
I wasn't happy with just saying I suspected that it may be possible, so I had a go at setting up full disk encryption on a VHD, however I hit a point where the Enable-Bitlocker command needed a TPM module. I know there are workarounds for this, but that could take a while, so I'll leave this as a POC of what I had in mind. Way off topic, I know for this site - but it was bugging me that I didn't have any code illustrate my idea.

Code:
$disk = New-VHD -Path VirtualDisk.vhdx -SizeBytes 1GB
$mounted = Mount-VHD -Path $disk.Path -Passthru
Initialize-Disk -Number $mounted.DiskNumber -PartitionStyle MBR
$partition = New-Partition -DiskNumber $mounted.DiskNumber -UseMaximumSize -AssignDriveLetter
Format-Volume -DriveLetter $partition.DriveLetter -Confirm:$false

#stymied here because I don't have a TPM module in my computer - there may be a workaround
$SecureString = ConvertTo-SecureString "1234" -AsPlainText -Force
Enable-BitLocker -MountPoint $partition.DriveLetter -EncryptionMethod Aes256 -Pin $SecureString

#clean up
Dismount-VHD -DiskNumber $mounted.DiskNumber
rm VirtualDisk.vhdx
 
This is overly complicated as the explicit creation of a loopback device is not necessary any more.

In short

Code:
apt-get install cryptsetup # (this might not even be needed)
dd if=/dev/urandom of=/some/path/to/some/file bs=1M count=200 # creates a file of size 200 MB
cryptsetup luksFormat /some/path/to/some/file
cryptsetup luksOpen /some/path/to/some/file someuniqueidentifier
mkfs.ext2 /dev/mapper/someuniqueidentifier
mount -t ext2 /dev/mapper/someuniqueidentifier /media/somemountpoint
#write files to /media/somemountpoint
umount /media/somemountpoint
cryptsetup luksClose someuniqueidentifier


So lines 1,2,3 and 5 are for set up and for day-to-day use you only need the open, mount, umount and close commands.

I sadly haven't found a way to do this via file manager, but maybe I'll get there...
 
greetings,
my name is mhogomchungu and i have a project called "zuluCrypt"[1] that provides a GUI way to create and open LUKS volumes as well as TRUECRYPT volumes.

Just though i should drop by and inform of my project.The reason i started the project is because i want to use cryptsetup instead of truecrypt for my encrypted volumes but i could not find any cryptsetup GUI front end that is easy to use like truecrypt GUI and i decided to write my own and share it the the rest of the FOSS community.

[1] I can not seem to be able to post a link here so just google for the project name and hopefuly google will take you to the project's page.
 
It really is a pain in the backside that device-mapper can only be used by root, otherwise regular users could easily use cryptsetup to build self-contained encrypted containers to securely store their important data, especially with the advent of btrfs and the ease with which these fs volumes can be expanded. Of course, this is a kernel issue, but it's been a thorn in my side for a few years now.
 

Members online


Top