Encrypt files and folders with AES-256 on OSX

Sat 10 October 2015

In this post I outline how I managed to implement compression with AES-256 on my mac.

Motivation

Some of our users need to be able to send each other files which contain sensitive data. The solution have to be easy to use, or otherwise they will not use it. To be able to exchange files with other platforms there also is a demand that the encryption used is AES-256.

Fine, our os have a built in option "Compress " when you right-click on a file or folder. This is maybe the most userfriendly way to compress a file, but sadly it does not allow for password protecting the archive(s). What I want is a "Compress and encrypt " option.

Planning

To be able to get my own elements in the right-click menu I can create a Automator service which takes selected elements from Finder as input and pass them through the workflow, great!

But how can I create encrypted archives on osx?

$ zip
Copyright (c) 1990-2008 Info-ZIP - Type 'zip "-L"' for software license.
Zip 3.0 (July 5th 2008). Usage:
zip [-options] [-b path] [-t mmddyyyy] [-n suffixes] [zipfile list] [-xi list]
  The default action is to add or replace zipfile entries from list, which
  can include the special name - to compress standard input.
  If zipfile and list are omitted, zip compresses stdin to stdout.
  -f   freshen: only changed files  -u   update: only changed or new files
  -d   delete entries in zipfile    -m   move into zipfile (delete OS files)
  -r   recurse into directories     -j   junk (don't record) directory names
  -0   store only                   -l   convert LF to CR LF (-ll CR LF to LF)
  -1   compress faster              -9   compress better
  -q   quiet operation              -v   verbose operation/print version info
  -c   add one-line comments        -z   add zipfile comment
  -@   read names from stdin        -o   make zipfile as old as latest entry
  -x   exclude the following names  -i   include only the following names
  -F   fix zipfile (-FF try harder) -D   do not add directory entries
  -A   adjust self-extracting exe   -J   junk zipfile prefix (unzipsfx)
  -T   test zipfile integrity       -X   eXclude eXtra file attributes
  -y   store symbolic links as the link instead of the referenced file
  -e   encrypt                      -n   don't compress these suffixes
  -h2  show more help

It seems that -e actually wil encrypt the archive for me, maybe I can script something around that? But first I want to see what encryption is actually is offering me.

$ man zip

No mention of ciphers there, but luckily zip belongs to the bits & pieces of osx that is opensource. Lets look into the source code and see if we can get some hints there.

*
  This encryption code is a direct transcription of the algorithm from
  Roger Schlafly, described by Phil Katz in the file appnote.txt.  This
  file (appnote.txt) is distributed with the PKZIP program (even in the
  version without encryption capabilities).
 */

if this is true, then this is not AES-256, which again means I cant use the built in zip.

After searching the Internet, I decided to give the commandline version of 7-zip a try. According to their documentation it supports AES-256. Which is exactly what I need.

Implementation

So the next step now is to actually install the commandline version of 7-zip, which I do with MacPorts.

    $ port search p7zip
    p7zip @9.38.1 (archivers)
        7-Zip implementation

    $ sudo port install p7zip

But since I am going to distribute this to multiple machines I want to compile the p7zip port to an distributable pkg so I can deploy them with Munki. I have done this before with Curl, so I just followed my own documentation and created a p7zip.pkg.

Remember that you have to compile the p7zip port for each version of osx you are going to deploy to, i.e 10.8, 10.9 and 10.10.

When the p7zip.pkg is installed I can compress and encrypt files by doing:

    7za a "archive.zip" "inputfile" -tzip -mem=AES256 -mx9 -p"password"

Make it userfriendly

I now have capabilities to compress and encrypt files, using AES-256. The last piece of the puzzle is to make it a bit more userfriendly as described earlier.

For this I need an applescript snippet to capture the password, and a shell snippet to do the compression with the supplied password.

Applescript:

    on run {input, parameters}
        tell application "System Events"
            display dialog "Password:" default answer "" with hidden answer
        end tell

        set pass to text returned of result

        return input & pass
    end run

Bash:

    # Get the password
    password=`echo "${@: -1}"`
    # Clean out the password (which is the last element in the input parameter list
    set -- "${@:1:$(($#-1))}"
    # Loop over all files and folders and compress them with the given password
    for f in "$@"
    do
    if [ -d "$f" ]; then
        /opt/uib/p7zip/bin/7za a "$f.zip" "$f" -tzip -mem=AES256 -mx9 -p"$password"
    fi

    if [ ! -d "$f" ]; then
        /opt/uib/p7zip/bin/7za a "$f.zip" "$f" -tzip -mem=AES256 -mx9 -p"$password"
    fi
    done

Chain with Automator:

Automator compress and encrypt workflow

Conclusion

By combining different tools I managed to get what I needed. The hardest part was debuging the various Automator approaches I tested.

Compress and encrypt service