On Mac OS X, Apple provides an option called FileVault, it is intended to transparently encrypt and decrypt anything stored in a users home folder. The system works by mounting an encrypted sparse disk image where the users home folder would otherwise be, this makes it compatible with just about everything a user would have been doing on the system. You would think that if you have FileVault turned on, your personal data, such as browsing history, thumbnails for your photographs, temporary files, and so on, would be encrypted. You would only be partially correct.

It is true that certain things are correctly encrypted, your Music files, anything on the Desktop, and application support files like preferences for instance. However, it cannot be assumed that running applications will correctly store sensitive information inside the home folder, indeed some of them dont and we know they dont. Safari 4 beta for instance stores visual previews of certain sites in /var/folders, which is outside the home folder and not encrypted or protected by anything but file permissions. Other applications may do the same thing, or worse.

The clear solution here is to encrypt the entire root volume, and PGP provides just such a solution in PGP Desktop 9 for Mac which includes their Whole Disk Encryption program. While i am sure it works and would probably meet the needs of many users, i dont have a copy of it (but would be glad to test it! :) ), and i dont like installing 3rd party kernel extensions. Perhaps once Truecrypt supports full system encryption on OS X i will give that a try, but until then i will make do with what i already have available to me.

What i do have available, is OS X built in tools for working with disk images. They support AES-128 and AES-256 encryption as well as dynamically expanding sparse images that will grow with use without taking up the whole drive with unused space. These tools can be accessed from the commandline before the full desktop is actually started, and this is what i have done. I have written a small shell script and a launchd item to execute it during boot. Currently it executes at an arbitrary point, but it seems to work well since that arbitrary point is almost always before the user has a chance to login. It may be better to execute it at a much earlier point in the boot process, but some specific services must be available first due to the way these commands work. If anyone has any advice as to what would be a good solution to make sure the script executes early in the boot process, by all means add a comment below. There are multiple systems to start services at boot time on OS X, but to my knowledge all of them have been relegated to legacy status and Launchd is taking over for all of them slowly.

I will also make available a pkg file for installing these scripts automatically, but without further babbeling, this is the primary script:


The script is too long to post here, but you should be able to open that link and read it in a nice big window :)

Currently at version 1 it is only setup to do the following folders:


While /private/var/log is not a temporary directory, it is one of the worst offenders of leaked data. I have seen full pathnames to personal files listed in various logfiles both because of application errors, crashes, and intentionally. If you are concerned with your privacy while on a Mac system, you will want to ensure that log files dont get stored on disk. You can turn off syslog but that does not prevent data from being leaked. Some applications write logs directly so turning off syslog has no effect on their ability to leak data. Also, on OS X Apple uses their own syslog, and it uses a database file to store everything it writes to the individual log files, so deleting or wiping those .log files does not get rid of the log data, it is still present in the database, however that database is also stored under /var/log so this encryption method should protect that as well.

There is another log directory, /Library/logs, however it does not appear that applications write anything but generic crash data and nonspecific information here, it could however be added to the script easily and i may do that.

Now back to the script. The individual sections are relatively simple, basically multiple independent keys are created in temporary bash variables from the /dev/urandom device. 64 bytes are used for the random key, this is a much longer and more random key than anyone could come up with and remember, so it is very secure. If needed one could draw from /dev/random instead to get higher quality random data, but that might cause a pause during boot or it could simply fail to work if entropy is not available to service all the read requests.

Then one by one, old sparseimages are deleted and new ones are created. We do this because the data is old anyway with the exception of /var/log. The point here is to prevent sensitive data from being actually stored anywhere as unencrypted plaintext, so throwing away the images after reboot makes sense.

Then, the disk images are created and mounted with a long string of options to the hdiutil command, which is a great command for working with disk images on OS X. Some of them are obvious, we are creating a sparse, encrypted HFS+ disk image, but also we want the volume to be owned by root:wheel so we set uid and gid to zero, and on mount (attach) we set union, which simply layers the disk image on top of whatever is already in the directory it is being mounted on (will discuss in detail shortly), and we set owners on to protect data in these directories from being read by anyone on the system. We also set nobrowse to prevent these volumes from showing up on the desktop or in the finder, because otherwise they will.

At the end of the individual sections we correct the permissions to match what OS X sets on those folders normally.

Now, a word about the union thing. Union mounting means an image or drive is mounted over top of a directory without actually replacing what was there. So the data that was already present is still there and accessible, but new data gets written to the image (which we encrypt with a random key and delete on reboot, making it disposable).

This technique could be used for a variety of purposes, but here it is ensuring that temporary application data and logs are never actually written to the disk in clear form, and upon reboot that data cannot ever be recovered because the key is no longer known (it was never stored anywhere but ram). Note that you could not actually keep system files in these encrypted containers because the system needs some of the files just to boot and to mount these images. It works the way i used it because these directories are just temporary areas.

Keep in mind this is a crude hack that could have unintended consequences, for instance i believe that when Disk Utility erases free space on the root volume it does so by writing to one of the temporary directories (/private/var/folders). This means you are only filling that specific sparse image and not actually erasing the rest of the free space on the drive. The individual images are limited to 10GB to prevent any of them from filling the root partition itself, however things can still go wrong if any of them become completely full.

Also note that because of the way it is currently executed at boot time with Launchd, not everything during the boot process gets written to these disk images because they arent mounted yet, some things are written to the original directories in the clear. This isnt a problem for privacy because the data that does get written to disk is general boot data and not user specific. If you wait a minute or 2 before login you can ensure that the images will be mounted before you ever do anything within your user account. If you login automatically or very quickly you will actually be able to see that the images are not always mounted yet, so again if anyone knows a good way to force the process to occur earlier during boot, let me know :)

While it is not a good idea to install this sort of hack without knowing what it does and without being able to control it or remove it, i will make a pkg available below that includes the launchd item and will automatically install both scripts.