English
Deutsch
  

Code


About Matthias Nott
Business Objects
Picture Galleries
Code
Technical
Download





Locations of visitors to this page

This is a short description on how you can set up encrypted directories on a linux file system. The idea is not to encrypt a whole file system, and not to use an encrypted container file, but to encrypt on a file by file basis.

 

The procedure should be totally transparent. Obviously, if someone "steals" your laptop, the machine should be worth nothing more than its amount of plastic, glass and metal. Particularly, if someone takes out the disk and puts it into his computer, he should not find any usable data.

 

The public key file is kept on a memory stick. Even if that stick is stolen, too, you still need your private key (which is in your head only), and it would mean to break the Geneva Convention to try to get at that private key...

 

The first thing that you need is encfs: encfs.sourceforge.net. You need the filesystem in user space option (CONFIG_FUSE_FS=m) enabled in your kernel, too.

 

Once you have installed encfs, imagine you have a directory /data/myuser which contains user data. First, create a backup of your data! Then you create a directory /data/... (that is, three ".") which is not so terribly visible and won't make too many people as curious on superficially seeing an "ls" compared to /data/secretstuff. You also create /data/.../data and /data/.../data/myuser. You then move /data/myuser to /data/myuser.old and create /data/myuser as an empty directory.

 

You are going to mount the encrypted content, which will reside in /data/.../data/myuser to the new mountpoint /data/myuser. You initiate that by saying

  1. linux:/data # encfs /data/.../data/myuser /data/myuser
  2. Creating new encrypted volume.
  3. Please choose from one of the following options:
  4.  enter "x" for expert configuration mode,
  5.  enter "p" for pre-configured paranoia mode,
  6.  anything else, or an empty line will select standard mode.
  7. ?> p
  8.  
  9. Paranoia configuration selected.
  10.  
  11. Configuration finished.  The filesystem to be created has
  12. the following properties:
  13. Filesystem cipher: "ssl/aes", version 2:1:1
  14. Filename encoding: "nameio/block", version 3:0:1
  15. Key Size: 256 bits
  16. Block Size: 512 bytes, including 8 byte MAC header
  17. Each file contains 8 byte header with unique IV data.
  18. Filenames encoded using IV chaining mode.
  19. File data IV is chained to filename IV.
  20.  
  21. -------------------------- WARNING --------------------------
  22. The external initialization-vector chaining option has been
  23. enabled.  This option disables the use of hard links on the
  24. filesystem. Without hard links, some programs may not work.
  25. The programs 'mutt' and 'procmail' are known to fail.  For
  26. more information, please see the encfs mailing list.
  27. If you would like to choose another configuration setting,
  28. please press CTRL-C now to abort and start over.
  29.  
  30. Now you will need to enter a password for your filesystem.
  31. You will need to remember this password, as there is absolutely
  32. no recovery mechanism.  However, the password can be changed
  33. later using encfsctl.
  34.  
  35. New Encfs Password:
  36. Verify Encfs Password:
  37. linux:/data # ls -la /data/.../data/myuser
  38. total 4
  39. drwxr-xr-x  2 root root  72 Feb 24 10:53 .
  40. drwxr-xr-x  5 root root 120 Feb 24 10:52 ..
  41. -rw-r-----  1 root root 239 Feb 24 10:53 .encfs5

You can see that a file .encfs5 has been created in /data/.../data/myuser. Now assume you have a memory stick and usually mount that to /mnt/memorystick. Create a directory .key on that memory stick (i.e., /mnt/memorystick/.key) and, in addition, create /mnt/memorystick/.key/data and /mnt/memorystick/.key/data/myuser. Then move /data/.../data/myuser/.encfs5 to /mnt/memorystick/.key/data/myuser/.

 

Keep a copy of .encfs5 in a safe location! This is your public key, so you will not be able to access your files anymore once you have lost that key file.

 

Finally, create a file /etc/crypto.conf with a content like

  1. #
  2. # Configuration of mount points for the crypted directories
  3. #
  4. # Resources can be encrypted using
  5. #
  6. #   encfs "Encrypted Content Location" "Mountpoint"
  7. #
  8. # The format of this file is
  9. #
  10. #   Resource Name    Encrypted Content Location    Mountpoint      Keyfile
  11. #
  12.  
  13. myuser           /data/.../data/myuser                 /data/myuser                 data/myuser/.encfs5
  14. java             /data/.../pgm/java                    /pgm/java                    pgm/java/.encfs5

You see that I've created another entry in the config file to show how it works. Finally, use the following perl script like "crypto mount myuser" to mount the directory for "myuser", or "crypto" or "crypto all" to mount all definitions or "crypto umount myuser" to unmount the directory for "myuser" or "crypto umount all" to unmount all definitions:

  1. #!/usr/bin/perl -w
  2. #
  3. # This is a script that mounts crypted file systems based
  4. # on public keys that have to be available on a memory stick.
  5. #
  6. # (c) 2006, Matthias Nott, MN Soft Branchensoftware
  7.  
  8.  
  9. use strict;
  10. use warnings;
  11. use File::Listing;
  12. use Term::ReadKey;
  13.  
  14. my $memorystick = "SanDisk";          # Vendor String of Memory Stick
  15. my $mountpoint  = "/mnt/memorystick"; # Mount point
  16. my $keyfiledir  = "$mountpoint/.key"; # Key Files Location
  17. my $configfile  = "/etc/crypto.conf"; # Configuration of Crypted File Systems
  18.  
  19. my $task        = "mount";
  20. my $target      = "all";
  21.  
  22. my $memstickmounted = 0;              # Will be set to 1 if memory stick was mounted
  23.                                       # specifically for this application
  24.  
  25. ($task,$target) = @ARGV if(scalar @ARGV>0);
  26.  
  27. if(!defined($target)) { $target = "all"; }
  28.  
  29. #
  30. # Test for availability of memory stick
  31. #
  32. if($task eq "mount" && !-d "$keyfiledir") {
  33.   my %vendors;
  34.   file: for (parse_dir(`find /sys/block -follow -iname "vendor" | xargs ls -l`)) {
  35.     #
  36.     # Get the file information
  37.     #
  38.     my ($name, $type, $size, $mtime, $mode) = @$_;
  39.  
  40.     next if not $name =~ m!/sys/block/sd./device/vendor!;
  41.  
  42.     my $devid   = $name;
  43.     my $devname = "";
  44.     $devid =~ s!/sys/block/([^/]+?)/.*!$1!;
  45.     open(VENDOR, "$name") || die "Cannot open: $!\n";
  46.     while(<VENDOR>) {
  47.       chomp;
  48.       s/\s+$//;
  49.       $vendors{$_} = $devid;
  50.       $devname = $_;
  51.     }
  52.     close(VENDOR);
  53.     last if $devname eq $memorystick;
  54.   }
  55.   die "Unable to find the $memorystick memory stick!" if(!defined($vendors{$memorystick}));
  56.  
  57.   if(length(`mount | grep "$vendors{$memorystick}"`) == 0) {
  58.     print "Mounting: $mountpoint\n";
  59.     system("mount \"/dev/$vendors{$memorystick}1\" \"$mountpoint\"");
  60.     $memstickmounted = 1;
  61.   }
  62.   die "Unable to load keys from memory stick!" if (!-d "$keyfiledir");
  63. }
  64.  
  65. open (CRYPTO, "<$configfile") || die "Cannot open: $!\n";
  66.  
  67. my $pass = "";
  68. if($task eq "mount") {
  69.   #
  70.   # Ask for password
  71.   #
  72.   ReadMode('noecho');
  73.   print "Enter Crypto Key: ";
  74.   $| = 1;
  75.   $pass = ReadLine(0);
  76.   chomp($pass);
  77.   ReadMode('normal');
  78.   print "\n";
  79. }
  80.  
  81. my $helped = 0;
  82. while(<CRYPTO>) {
  83.   if(!/^#.*$/) {
  84.     if(/^([^\s]+?)\s+?([^\s]+?)\s+?([^\s]+?)\s+?([^\s]+?)$/) {
  85.       #
  86.       # Resource name | Encrypted Content Location | Mountpoint | Keyfile
  87.       #
  88.       if($task eq "mount") {
  89.         if(($target eq "all") || $target eq $1) {
  90.           if(!-d $3) {
  91.             system("mkdir $3");
  92.           }
  93.           if(length(`mount | grep "$3"`) == 0) {
  94.             print "Mounting: $1 -> $3\n";
  95.             system("echo $pass | ENCFS5_CONFIG=\"$keyfiledir/$4\" encfs -S --public \"$2\" \"$3\"");
  96.           }
  97.         }
  98.       } elsif($task eq "umount") {
  99.         if($target eq "all" || $target eq $1) {
  100.           if(length(`mount | grep "$3"`) != 0) {
  101.             print "Unmounting: $1 -> $3\n";
  102.             system("umount -f \"$3\"");
  103.           }
  104.         }
  105.       } elsif(!$helped++) {
  106.         print "Options: mount|umount all|resource name\n";
  107.       }
  108.     }
  109.   }
  110. }
  111. close(CRYPTO);
  112.  
  113. if($task eq "umount" || $memstickmounted) {
  114.   if(length(`mount | grep "$mountpoint"`) != 0) {
  115.     print "Unmounting: $mountpoint\n";
  116.     system("umount \"$mountpoint\"");
  117.   }
  118. }

The above Perl script assumes you are using the same password for all mounts; if this is not the case, you'll have to rewrite it accordingly. When you backup your file system, simply exclude /data/myuser from the backup process, as it will be covered by /data/.../data/myuser. If you now wonder what is in /data/.../data/myuser: move all your content of /data/myuser.old to /data/myuser while the crypted directory is mounted. Then hava a look at /data/.../data/myuser: You see only garbled directory entries and garbled file contents, whereas in /data/myuser you see everything just as before. When you "crypto umount", you get an empty directory /data/myuser.

 

Performance wise, I encrypt all my data using that mechanism. Behind the scenes, a 256 bit encryption is used, so for the time being, the data can be regarded as safe (provided you keep /tmp/ in a ramdisk, etc.). I am pretty happy with that system. It is even normally not necessary to "umount" the file systems while you go on a coffee break: simply lock your screen. Unmounting the file systems would require closing all files on them which may be inconvenient. If you lock the screen, people would have shut down your computer and put your disk into another computer, in which case the file systems would have been unmounted automatically.

 

Safety wise, it is a good idea to use a file by file method, as you do not risk to loose all your data because of a loss of a container file. In addition, loopback mounting a container file seems elegant, yet you're going to be limited to the size of the container file as you initially created it.

 


24.02.2006, 11:21 Copyright © 2005 MN Soft Industry Software, 108, route de la Fin, CH-1874 Champéry
Tel.: +41 797 844554; Fax: +41 860 797 844554, Responsible: Matthias Nott., mn(at)mnsoft.org
Top of Page