Simulating encrypted physical disk in OS X Creative Commons License

posted in the late evening by Constantinos. Filed under Code, OS X

This post was originally published in 2008
The tips and techniques explained may be outdated.

I’ve always wanted to do this: have my personal files on a memory stick, encrypted, and when I insert the memory stick in a USB port then OS X asks me for a password to decrypt the files. Unfortunately, this functionality isn’t offered directly as you can’t (at least from what I’ve tried and read) encrypt a device directly. What you can do however is create encrypted disk images, and place them in your thumb drive. There are two disadvantages with this method: First the process isn’t automatic, first the drive mounts, then you have to double-click on the encrypted disk image to mount it, and second after you do that you have two volumes on your Desktop. One for the thumb drive, and one for the encrypted image.

Obviously, in my obsessive compulsive need to have everything work as I want them, I didn’t like this. As a result, I created the following scripts (including a folder action) which pretty much simulate the whole experience. These scripts were only tested on 10.5.1, but they should work on at least Tiger.

Update 2008-02-01: Download all the scripts featured on this page in a single archive file.

Update 2008-02-08: The automount and prepare scripts in the download archive were reversed (my mistake) which is now fixed. I also added compatibility for sparsebundle types, and the password entry when preparing a drive is now hidden (thanks John!)

There are two steps to the process. The first step is to prepare the memory stick, and the second is to configure the folder action. The first step only has to be applied once, and works best on a freshly formatted memory stick, however it doesn’t have to be formatted; it will use all the available space to create the encrypted image. Save the following script as an application bundle somewhere, plug in the memory stick you wish to use as your ‘encrypted storage’, and drag-drop the mounted volume on the bundle. It will ask you for a password (which is typed in the clear – fair warning), then after a few minutes (with the default settings) it will finish creating the encrypted image, mark the entire volume as hidden, and eject the drive.

(*
    Prepare secure drive droplet
    Part of 'Simulating encrypted physical disk in OS X' by Constantinos Neophytou
    http://www.cneophytou.com/2008/01/30/simulating-encrypted-physical-disk-in-os-x/
 
    Version 0.1.1
*)
 
property imageType : "UDIF" (* one of "UDIF", "SPARSE" or "SPARSEBUNDLE" - the latter two have faster creation times, but leave empty space on the device *)
property thePass : ""
 
on open dropped_item
    set this_vol_alias to (dropped_item as alias)
    try
        tell application "Finder"
            if the kind of this_vol_alias is "Volume" then
                set freeSpace to free space of this_vol_alias
                set volumeName to quoted form of POSIX path of this_vol_alias
                set imgSize to (round (freeSpace - (1024 * 1024 * 1)) / (1024 * 1024)) (* leave 1mb of free space, just in case *)
 
                display dialog "Enter password for encrypted image:" default answer thePass with hidden answer
                set thePass to text returned of result as string
 
                set createImg to "hdiutil create " & volumeName & ".secure -size " & imgSize & "m -fs HFS+ -type " & imageType & " -encryption -volName Secure -passphrase " & thePass
                set thePass to "" (* clear the password from memory *)
                set hideVol to "chflags hidden " & volumeName
                with timeout of 600 seconds
                    do shell script createImg
                    do shell script hideVol
                    do shell script "hdiutil detach " & quoted form of POSIX path of this_vol_alias
                end timeout
            else
                display alert "This script can only be executed on volumes"
                return
            end if
        end tell
 
    on error error_message number error_number
        display dialog error_message buttons {"OK"} default button 1
    end try
end open

Download all scripts

At this point, the memory stick is configured for use with the folder action. Warning: If you remove the drive and plug it back in without the folder action being in place, the disk will mount but it won’t show up in the Finder. You will have to use Disk Utility or the Terminal to un-mount it. Go ahead and copy the following code, save it as a script under /Library/Scripts/Folder Action Scripts/, and attach it as a folder action to /Volumes.

(*
    Automount secure drive folder action
    Part of 'Simulating encrypted physical disk in OS X' by Constantinos Neophytou
    http://www.cneophytou.com/2008/01/30/simulating-encrypted-physical-disk-in-os-x/
 
    Version 0.1.1
*)
 
property secureName : ".secure"
 
on adding folder items to this_folder after receiving these_volumes
    try
        tell application "Finder"
            set the volume_list to every file of this_folder
            (* go through all entries in /Volumes/ *)
            repeat with i from 1 to number of items in volume_list
                set this_item to the original item of item i of volume_list
                if the kind of this_item is "Volume" then
                    set this_disk to (this_item as alias)
 
                    (* is this item the newly mounted disk? *)
                    if this_disk is in these_volumes then
                        (* iterate through all files in the root of disk *)
                        set searchCmd to "ls -d " & quoted form of POSIX path of this_disk & secureName & "*"
                        (* check to see if a hidden secure image  is available *)
                        set searchResult to ""
                        try
                            set searchResult to do shell script searchCmd
                        end try
                        (* mount the secure image *)
                        if (searchResult starts with "/Volumes") then
                            set hiddenFile to POSIX file searchResult as alias
                            open hiddenFile
                        end if
                    end if
                end if
            end repeat
        end tell
    end try
end adding folder items to
 
on removing folder items from this_folder after losing these_items
    tell application "Finder"
        try
            set the volume_list to every file of this_folder
            (* go through all entries in /Volumes/ *)
            repeat with i from 1 to number of items in volume_list
                set this_item to the original item of item i of volume_list
                if the kind of this_item is "Volume" then
                    set this_disk to (this_item as alias)
 
                    set searchCmd to "ls -d " & quoted form of POSIX path of this_disk & secureName & "*"
                    (* check to see if a hidden secure image  is available *)
                    set searchResult to ""
                    try
                        set searchResult to do shell script searchCmd
                    end try
                    if (searchResult starts with "/Volumes") then
                        (* eject the volume *)
                        do shell script "hdiutil detach " & quoted form of POSIX path of this_disk
                        (* eject this_disk *)
                        delay 1
                        display alert "It is now safe to remove the encrypted disk"
                        return
                    end if
                end if
            end repeat
        end try
    end tell
end removing folder items from

Download all scripts

Now whenever you plug in the thumb drive, this script will kick in and try to open the encrypted image which will in turn make the Finder ask you for a password. Additionally, when you un-mount the encrypted image, it will find the thumb drive and un-mount it as well. You should wait for the confirmation dialog saying it’s safe to remove the device before doing so, as ejecting the encrypted image is not the same as ejecting the drive, the folder action has to kick in and do that for you.

There are a couple of issues with this. The first one, I haven’t been able to find a decent solution for. If after you plug in the memory stick and you’re asked for a password for the encrypted device, you either enter the wrong password three times or press ‘Cancel’, then the encrypted image will not mount, but the memory stick will remain mounted. To eject it, you will have to use Disk Utility or the Terminal. The second one, is reverting the memory stick to its proper state. To do that, I created another script which you can just run by itself, after plugging in the memory stick and pressing ‘Cancel’ when asked for the encrypted image password (i.e. it uses the ‘bad’ state described in the previous problem). When run, the script will find the memory stick that contains the encrypted image and ask if you wish to revert it. If you press ‘Yes’, it will then ask if you wish to preserve the secure image. Pressing ‘Yes’ will move the secure image on your Desktop (under the name secure.dmg), otherwise it will just delete it from the drive. It will also restore the hidden status of the thumb drive and eject it, so the next time you plug it in it will behave normally:

(*
    Restore secure drive
    Part of 'Simulating encrypted physical disk in OS X' by Constantinos Neophytou
    http://www.cneophytou.com/2008/01/30/simulating-encrypted-physical-disk-in-os-x/
 
    Version 0.1.1
*)
 
property secureName : ".secure"
tell application "Finder"
    try
        set the volume_list to every file of (POSIX file "/Volumes/" as alias)
        repeat with i from 1 to number of items in volume_list
            set this_item to the original item of item i of volume_list
            if the kind of this_item is "Volume" then
                set this_disk to (this_item as alias)
 
                set searchCmd to "ls -d " & quoted form of POSIX path of this_disk & secureName & "*"
                (* check to see if a hidden secure image  is available *)
                set searchResult to ""
                try
                    set searchResult to do shell script searchCmd
                end try
                if (searchResult starts with "/Volumes") then
                    display dialog "Restore secure disk " & (name of this_disk) & "?" buttons ["No", "Yes"] default button 2
                    set the_button to button returned of result
                    if (the_button is "Yes") then
                        display dialog "Preserve copy of secure data on Desktop?" buttons ["No", "Yes"] default button 2
                        set the_button to button returned of result
                        if (the_button is "Yes") then
                            with timeout of 600 seconds
                                do shell script "mv " & quoted form of searchResult & " ~/Desktop/secure.dmg"
                            end timeout
                        else
                            do shell script "rm -f " & quoted form of searchResult
                        end if
                        set volumeName to quoted form of POSIX path of this_disk
                        do shell script "chflags nohidden " & volumeName
                        do shell script "hdiutil detach " & volumeName
                        delay 1
                        display alert "Device restored. It is now safe to unplug the device."
                        return
                    end if
                end if
            end if
        end repeat
 
    on error error_message number error_number
        display dialog error_message buttons {"OK"} default button 1
    end try
end tell

Download all scripts

As always, these scripts are provided without any warranty, and any suggested improvements are more than welcome!

5 Responses to “Simulating encrypted physical disk in OS X”

  1. 1. Comment by John Slaughter
    on 8 Feb 2008 @ 2:35 pm

    Here’s a tip about fixing the password being visible while typing it.

    Change:
    display dialog “Enter password for encrypted image:” default answer thePass

    To:
    display dialog “Enter password for encrypted image:” default answer thePass with hidden answer

    That will make the password entry into bullets.

    =)
    -John

  2. 2. Comment by Jim Hoyt
    on 8 Feb 2008 @ 5:11 pm

    Please correct me if I’m wrong but the download tgz appears to have the contents of the prepare/mount scripts backwards, i.e the prepare script starts with “on adding folder items” and the mount script starts with “on open dropped item.”

    I’ll wait ’til I hear from you before continuing.

    Sure looks like a neat idea though.

    Cheers,
    Jim

    PS – Under Leopard unmounting a drive that has two volumes on it presents a dialog asking if unmounting the selected or both volumes is desired. This could help solve the “cancel” problem. You just make one volume encripted and leave the other alone. Both will mount on insert but only one will be visible. Canceling the password request will leave the hidden volume open but it can then be ejected by answering “both” when ejecting the visible one.

  3. 3. Comment by Constantinos
    on 8 Feb 2008 @ 5:22 pm

    [quote post=”107″]Here’s a tip about fixing the password being visible while typing it.[/quote]

    Excellent! Thanks!

    [quote post=”107″]Please correct me if I’m wrong but the download tgz appears to have the contents of the prepare/mount scripts backwards, i.e the prepare script starts with “on adding folder items” and the mount script starts with “on open dropped item.”[/quote]

    Whoops 🙂

    Yes, you’re right, I accidentally reversed the scripts for those two files. Just fixed it.

    I also made a small fix in the folder action script to enable it to work with sparsebundles (which in the linux environment just appear as directories, not files).

  4. 4. Comment by Constantinos
    on 8 Feb 2008 @ 5:30 pm

    [quote post=”107″]Under Leopard unmounting a drive that has two volumes on it presents a dialog asking if unmounting the selected or both volumes is desired.[/quote]

    Yes, that’s correct, except to use this feature the drive has to be split into two partitions (so there are two separate volumes) and have one of them encrypted. If we could do that using the default Leopard installation, then we could also do it with one partition.

    With this script, you only have one volume, which is hidden. Your encrypted ‘volume’ is actually an encrypted disk image which resides on the hidden partition. So this wouldn’t work.

    Also, when you hit ‘Cancel’, the encrypted volume doesn’t mount. Therefore, there are no visible volumes on the Desktop that belong to your encrypted memory stick, so this feature cannot be used.

    TrueCrypt has recently released an OS X version, but I have not been able (or have not tried hard enough) to make it work for me. I believe it uses MacFUSE, and actually encrypts the volume. I still prefer this method as it doesn’t rely on any third-party plugins 🙂

  5. 5. Comment by fred
    on 2 Sep 2008 @ 8:11 pm

    And there’s OSXCrypt, http://www.osxcrypt.org (command line version of TrueCrypt).