Encrypted Core Storage Home Folder on Mac OSX
This article was last edited over 3 years ago. Information here may no longer be accurate. Please proceed with caution, and feel free to contact me.
So you want to encrypt your $HOME
on your Mac but
nothing else?
Let’s stop right here.
The built in option for FileVault full disk encryption is the standard on a Mac, and I recommend going that route for encryption. It is a fairly big pain to do what you’re asking.
Though, it is possible, and that is what this guide will help you to accomplish. Although it is complicated, it is possible to encrypt a user’s home folder independently of the rest of the system. We can use a keyfile to encrypt our home, and automatically mount it at boot.
A couple caveats.
- Again, I have to stress, FileVault is so much simpler. Or VeraCrypt.
- You must be comfortable using a USB key to decrypt your drive.
-
My process works 99% of the time, but about once every few
months my
$HOME
fails to mount properly and I must reboot to try again.
Full disk encryption is better than partial disk encryption, and my process certainly has some holes. It is up to you to be as secure (paranoid) as you want.
Administrator account
Create an Administrator
user on your Mac (with
Administrator access of course) and log out of your account and
log in as that user.
While it may be possible, I do not think it’s a good idea to mess with the home folder of a user while that user is logged in. That is why I ask you to create the Administrator user account.
Not only should you use that secondary account to follow these instructions, but you should keep that account around and never encrypt its home.
Why? Well, if your encrypted home folder fails to mount at boot time for some reason, you may be locked out of your Mac. That’s no fun. You can probably fix things via the recovery tools if that happens, but having a secondary admin account will greatly ease your burden if you need to troubleshoot. It’s your choice, but be warned, if something goes wrong and you get locked out of your machine, it will probably be very frustrating and annoying.
Create a keyfile
I believe that a keyfile is the only way to accomplish the goal of this article.
I cannot find any way to accomplish our goal using a password prompt. I don’t think you can inject/prompt for a password in the standard boot process without using a file that can be read via script.
I am naming my keyfile willencryptedhome.key
. The
file should contain nothing but the password.
thePassw0rd
That is a trivial example. In reality, this is how I generated my keyfile.
# 1023 chars is the longest allowed passphrase here.
cat /dev/urandom | env LC_CTYPE=C tr -dc 'a-zA-Z0-9' | fold -w 1023 | head -n 1 > willencryptedhome.key
Find a USB drive. Bonus points if it has a “read only” switch on it like the Kanguru USB drives that I use.
Format the USB drive as MS-DOS (FAT), with a Master Boot Record,
using Disk Utility. Name the drive KEYDRIVE01
or
something that’s reasonably unique.
Copy your keyfile to the root of KEYDRIVE01
.
You should backup this keyfile somewhere secure. If you lose it, you will forever lose access to your encrypted disk.
Set up our encrypted disk
I highly recommend using a dedicated disk to house this encrypted home of yours. What I mean is, a separate, distinct disk from your OS disk.
In my case, I’m using a brand new ~500GB SSD drive to act as my encrypted home.
For clarity, I’m going to refer to this disk as the “encrypted home”, even though it’s not encrypted just yet.
With your machine powered off, plug in your new encrypted home disk to your Mac. Boot up and open up your terminal.
Find the id of the disk that will server as your encrypted home.
diskutil list
My encrypted home disk is brand new and so has no partitions.
/dev/disk0 (internal, physical):
#: TYPE NAME SIZE IDENTIFIER
0: *480.1 GB disk0
... etc ...
Be extremely certain that you’re looking at the correct disk before proceeding. If you choose the wrong disk, you may lose data.
Create a corestorage
Logical Volume Group
on your encrypted home disk.
Warning: this will erase the disk. Note that I am
running this command against /dev/disk0
based on the
output of the command above. This will almost certainly
not be the same for you, so read carefully!
I am using ENCRYPTEDHOME
for the Core Storage logical
volume group name, but you use whatever you like.
diskutil corestorage create ENCRYPTEDHOME /dev/disk0
Your encrypted home disk layout should look something like this if
you do another diskutil list
.
/dev/disk0 (internal, physical):
#: TYPE NAME SIZE IDENTIFIER
0: GUID_partition_scheme *480.1 GB disk0
1: EFI EFI 209.7 MB disk0s1
2: Apple_CoreStorage ENCRYPTEDHOME 479.8 GB disk0s2
3: Apple_Boot Boot OS X 134.2 MB disk0s3
... etc ...
Create a volume inside the Core Storage
Logical Volume Group
that we just created a moment
ago. I am calling my volume
WILLENCRYPTEDHOME
. You can name it however you like,
but then make sure you use your updated name(s) in the
rest of my steps.
diskutil corestorage createVolume ENCRYPTEDHOME jhfs+ WILLENCRYPTEDHOME 100%
Encrypt your encrypted home disk Core Storage volume using the key we created earlier.
cat /Volumes/KEYDRIVE01/willencryptedhome.key|diskutil corestorage encryptVolume WILLENCRYPTEDHOME -stdinpassphrase
Unlock our encrypted disk at boot
Great. Now we have an encrypted drive and a USB key to unlock it, but how do we unlock it at boot when we need to login? OS X has no built in mechanism for this, so we’ll have to script it ourselves.
Technically, we can’t unlock the drive as part of the login process. At least, not to my knowledge. So, we must unlock the disk at boot time. We’ll unlock it then using our USB key.
Get the UUID of your USB key.
wills-iMac:~ will$ diskutil list | grep KEYDRIVE01
1: Apple_HFS KEYDRIVE01 1.9 GB disk4s1
wills-iMac:~ will$ diskutil info disk4s1 | grep "Volume UUID"
Volume UUID: 35B0AB1F-AF54-3A8B-8C95-8DA9833CB0E1
Get the UUID of your encrypted Logical Volume
. Note,
it’s the last item in the list.
wills-iMac:~ will$ diskutil corestorage list | grep "Logical Volume"
+-- Logical Volume Group C3E498E5-BADE-4367-9979-D6E541D37989
+-> Logical Volume Family 7E96AFD1-3B18-4C48-8537-8491B35DF73A
+-> Logical Volume 0C4997C8-EE93-4723-813F-D60A50872B60
Create a file with the following contents at
/opt/mount.sh
.
Replace YOUR_USB_KEY_UUID
and
YOUR_ENCRYPTED_VOLUME_UUID
in the script below with
the correct UUIDs for your USB key and encrypted volume
found when you ran the commands above!
Modify the script as needed for your system. For instance, your keyfile probably has a different file name than mine.
#!/bin/bash
USB_KEY_UUID=YOUR_USB_KEY_UUID
ENCRYPTED_VOLUME_UUID=YOUR_ENCRYPTED_VOLUME_UUID
LOG=/tmp/mount.log
echo "mount attempted at $(date)" > $LOG 2>&1
# Must ensure the USB key is mounted so we can access the keyfile.
diskutil mount $USB_KEY_UUID >> $LOG 2>&1
diskutil list >> $LOG 2>&1
KEY_NAME=$(diskutil info $USB_KEY_UUID | grep "Volume Name" | awk '{print $3}')
echo $KEY_NAME >> $LOG 2>&1
# Read the key.
password=$(cat /Volumes/$KEY_NAME/willencryptedhome.key)
# Mount encrypted volume using the key.
printf $password|diskutil corestorage unlockVolume $ENCRYPTED_VOLUME_UUID -stdinpassphrase
Lock that script down a bit and make it executable.
sudo chown root:wheel /opt/mount.sh
sudo chmod 500 /opt/mount.sh
sudo chmod +x /opt/mount.sh
OK, so how do we get that to run at boot?
Create a file at
/Library/LaunchDaemons/com.willhaley.mac.startup.mounthome.plist
using these contents.
Again, you can rename that file if you want, but make sure you update the name appropriately elsewhere!
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>RunAtLoad</key>
<true />
<key>Label</key>
<string>com.willhaley.mac.startup.mounthome</string>
<key>ProgramArguments</key>
<array>
<string>/opt/mount.sh</string>
</array>
</dict>
</plist>
Set our mount script to run at boot.
launchctl load -w /Library/LaunchDaemons/com.willhaley.mac.startup.mounthome.plist
Now comes the ultimate test. Keep your USB key plugged in, and reboot. Log in as any user and verify that you can see your mounted drive in the Finder.
Create a new folder in your encrypted volume. Reboot.
Do you see your folder in the encrypted drive? Great. Data is persisting as we’d hope.
Try unplugging your USB key and rebooting. You should see that the encrypted home disk does not mount now. Re-connect your USB key and reboot again.
Hopefully the encrypted home disk is mounting properly each time you reboot as long as the USB key is plugged in.
If your encrypted home is failing to mount automatically, take a step back and try to see where you went wrong.
Can you run the mount.sh
script manually? Do you see
any errors? Do you see a file created at
/tmp/mount.log
indicating that a mount was even
attempted? Keep at it. I’m sure you’ll figure it out,
and my apologies if I left out a step.
Move your $HOME data to the encrypted disk
You may not have paid attention at the beginning, but to reiterate, I highly recommend that you log out of your account and log in as another administrator for these next steps.
Once you have logged in as another user, we can copy data from your old unencrypted home directory to the new encrypted home location.
rsync -avr /Users/will/ /Volumes/WILLENCRYPTEDHOME/
Mount your encrypted disk as your new $HOME
Our encrypted volume should mount automatically at boot now, but
you’ll note it’s mounted under
/Volumes
by default. We do not want that. We want it
mounted at $HOME
. Although it’s possible to
re-define where $HOME
is, or do a mount bind, I am
not entirely comfortable messing with those. I feel like that
would be very non-standard and may not play well on a Mac.
So instead, we will mount the encrypted home disk over our
standard /Users/$USER
path.
Let’s go back and edit our
/opt/mount.sh
script. We have a couple more lines to
add.
At the bottom, add these lines so that from now on, your encrypted
home volume will mount at /Users/will
(or whatever is
applicable).
# This looks odd, but I've found that occasionally it fails to unmount the first
# time, so adding a loop so we can re-try.
MAX_ATTEMPTS=10
ATTEMPT=0
while [ "$(diskutil info $ENCRYPTED_VOLUME_UUID | grep -i "Mounted" | awk '{print $2}')" == 'Yes' ] && [ $ATTEMPT -lt $MAX_ATTEMPTS ]; do
sleep 1
echo "$ENCRYPTED_VOLUME_UUID is mounted. Attempt: $ATTEMPT of $MAX_ATTEMPTS" >> $LOG 2>&1
diskutil umount $ENCRYPTED_VOLUME_UUID >> $LOG 2>&1
ATTEMPT=$((ATTEMPT+1))
done
diskutil mount -mountPoint /Users/will $ENCRYPTED_VOLUME_UUID >> $LOG 2>&1
Reboot again. Your machine should now be using the encrypted
volume as your /Users/will
folder.
Clean up
Once you’re satisfied and your data is backed up securely
and your USB key is backed up securely, then you should
delete your old home directory at
/Users/will
(or wherever) from the unencrypted disk.
After all, what is the point of encrypting our
$HOME
if the old unencrypted data is still there in
the open?
Be extremely careful that you are deleting the data from the unencrypted disk, and not from your encrypted disk.
These steps took a lot of trial and error. FileVault is a much safer and easier way to get encryption, and although I have not used VeraCrypt, it is probably much simpler too.
For any of this to be worthwhile, please don’t leave your USB key plugged in to your Mac when you leave the house ;)
Citations
This site was a huge help in understanding Core Storage.
This site
was a huge help in understanding Launchd
and boot
scripts in OS X.