Personally Encrypted IMAP Storage


Wiretaps require a ‘minimum disruption of service’, which the courts have determined means that the government cannot force you to change your system to facilitate wiretaps except as explicitly detailed in statute.

The eff lawyers said we would probably win, and they would be interested in litigating, a case in which the government attempted to require us to change our systems. It does raise the question why hushmail did not make this case in court when faced with a wiretap, but what we know of the case is little.

The system design change that would be most useful for us is this: user’s email is encrypted in such a way that we cannot get at it (using a password protected private key stored via a one way hash). In the user control panel, users would have the option of high security or low security: high would mean they would need a good password. low would mean we would store a copy of their password so that we can restore their mail if they forget their password.

software available

The system design for this would need to happen at the IMAP server level. our current imap server, courier, is venerable, but there are many newer IMAP servers with more modular and maintainable designs:

  • dovecot: written in c, uses maildirs.
  • bincimap: written in c++, uses maildirs.
  • archiveopteryx: written in c++, uses postgres for mail storage.
  • dbmail: written in c, uses mysql, postgres, or sqlite for mail storage.

All four claim to be more secure, more module, and faster than previous generation imap servers (courier, imapd, etc). the db backed ones claim to be faster than the maildir backed ones. They are GPL, except for archiveopteryx which is dual licensed using a license based on the GPL (you can also get a commercial license).

common problems

storing private keys
In all scenarios, each user will likely have a private GPG key that is used for encrypting their storage. This key is not used for signing email (although I supposed it could be used for that if you didn’t find the idea private GPG keys on the server repellent). Rather than store these private keys by username, the private keys should be stored using a hash of the user’s name, their password, and a shared in-memory secret. This is so that there is enough bits to hash on and so you could not brute force derive reverse of any particular hash.

mail delivery
Delivery of mail to an encrypted mailbox is going to be tricky. The mailbox is not available to the server unless there is an active login session with the user. The strategy that we will have to develop is some way to spool up incoming mail and then trigger delivery when the session is created.

One possible way of approaching this would be:

  1. every user has a file path for their secure maildir and their insecure maildir. eg:
    • /maildir/
    • /maildir/
  2. their maildir path then is a link to one of these. eg:
    • /maildir/ —> /maildir/
  3. when the user logs in, an encrypted loopback devices is mounted at the location of their secure maildir (this can be triggered by the after login hook of courier, probably other imap daemons have something like this).
  4. the active maildir is then symlinked to the mount point of the loopback:
    • /maildir/ —> /maildir/
  5. all the mail that was delivered to the insecure maildir is then moved to the secure maildir.
  6. after a set period of time with no account activity, the secure loopback device is unmounted and the active link is returned to insecure maildir.

This of course means that the user’s email is available, in unencrypted form, on the server until they login.

the sqlite approach

One approach is to use dbmail + sqlite + encryption extension.

It is possible to set up dbmail to use a different sqlite database for every user who logs in (although this requires a separate dbmail process that stays alive for the entire session). The personal sqlite database could be encrypted using some server secret and the user’s passphrase—but I am not sure if you can use a GPG key for this.

Here is the thread in the mailing list about this: (although no hints on how to actually set it up)

There is a free (BSD-style license) implementation of SQLite encryption called SQLCipher.

There are also three commercial implementations: SEE with source ($2000), sqlite-crypt ($128), sqlcrypt ($149).

Some guy once set up dbmail to be chrooted for each user, using a separate sqlite db per user. Here is what he remembers:

I can try, although it’s been a few years at this point. Most of this may sound like rambling, but I’ll try to clear up anything that I’ve muddled on.

Firstly, I used dbmail -n -v so I could control while it was awake. Each dbmail user started up a separate copy using a unix domain socket.

Each database had a secret password/username that was known to a frontend perl script which ran from tcpserver, so we had:

tcpserver dbmail

The frontend handled the login sequence, and then started the copy of dbmail, logged into the system, and proxied the connection back to the user.

Almost all the code I needed went into dbmail- the wasn’t very long- like 200 lines or so.

I’m afraid I don’t have the frontend perl script anymore, but i’m not up to date on dbmail anymore so even if I could find it, it’d be some efforts getting it to work again.

the loop_aes approach

We could create a separate loopback partition for every user’s maildir. Suppose my maildir is stored at /maildir/e/elijah. That directory would be empty, but when I login an encrypted image will get mounted there.

Unfortunately, there is a low limit in most kernels on the number of loop devices that you can define. We can work around this problem by compiling our own kernels and by being aggressive about destroying the devices when they are no longer needed.

We don’t have any idea what the performance considerations are of having a hundred different encrypted partitions mounted at the same time, each with different keys.

The advantage of this approach is that we can use any maildir backed IMAP daemon, and it uses free software.