Automatically Encrypt my Org Journal Diary while Syncing
1. Motivation
I’ve long been keeping a private diary/journal with Org Journal in Emacs. For long, I’ve been writing on a single PC at home with no online syncing or real-time backup out of privacy concerns. This is inconvenient, because I’m not always home, and unsafe, because the disk may break down.
Fortunately, Org Journal supports automatic GnuPG (GPG) encryption, so each Journal file will be automatically encrypted each time we save the file. Thus, it is safe to sync my encrypted files with Dropbox. In this blog post, I’ll describe:
- how I set up GnuPG and Org Journal to enable encryption;
- how I migrate (archive) old journal files to this new system.
2. Setting up GPG
GPG is a nice tool for asymmetric encryption. Asymmetric encryption, in short, uses a public key to encrypt the secret and a private key to decrypt the secret (in this case my diary). The private key must be kept private and safe — if it is disclosed, somebody else can decrypt my secret; if it is lost, I won’t be able to decrypt my own journal (until the era of quantum computing:-)).
GPG should ship with most Linux distributions and Mac OS. Windows users will need to install GPG4win. The first step is to generate a GPG key pair, see Steps 1–12 in this Github tutorial.
I would like to edit my journal on multiple machines, and it’s therefore necessary to export this key pair to my other machines. First, to list all keys:
gpg -k
To export the public key:
gpg --armor --output pub.key --export example@email.com
where pub.key
is the file name, and the email address is corresponds to the key to be exported.
To export the private key, use 1:
gpg --armor --export-secret-keys example@email.com | gpg --armor --symmetric --output mykey.sec.asc
This will prompt for a passphrase to (symmetrically) encrypt my private key.
After sending the keys to another machine, I import the keys. For the public key:
gpg --import pub.key
and the encrypted private key:
gpg -d mykey.sec.asc | gpg --allow-secret-key-import --import
and I’ll be prompted for passphrase twice, the first one being the symmetric decryption during export, and the second one being the one I entered during key pair generation.
The keys must be trusted after import, otherwise I’ll be warned when using that key. To trust the key, type:
gpg --edit-key example@email.com
and I enter an interactive prompt which looks like this:
gpg>
type trust
and then hit ENTER
and choose 5 (ultimate) and then type quit
.
That’s it!
3. Org journal settings
Setting Org journal is simple — just set
(setq org-journal-encrypt-journal t)
in my config file. It is also possible to encrypt certain entries with Org Crypt. See the Org Journal readme page.
I used to keep separate journal files for each day (i.e. org-journal-file-type
is 'daily
), but I realised that to search over older journal files with org-journal-search-forever
is rather slow because all files must be decrypted one by one.
Thus, now I use a single file for each year:
(setq org-journal-file-type 'yearly org-journal-file-format "%Y.org")
4. Archiving old journal files
So now what to do is my old, daily journal files? I would like them to be encrypted, synced and searchable.
My first attempt was to encrypt them one by one with the same key and then delete the original .org
files.
However, this again makes it rather slow to search over all files with org-journal-search-forever
.
So my solution is to merge them into one big .org
file and then encrypt it.
This won’t enable me to search with org-journal-search-forever
but I can search within the buffer with swiper
.
The Elisp code for merging is:
(with-current-buffer (get-buffer-create "old-journal.org") (let ((filelist (with-temp-buffer (insert-directory (concat (file-name-as-directory org-journal-dir) "*.org") nil t t) (split-string (buffer-string))))) (dolist (file filelist nil) (let ((file-string (with-current-buffer (find-file-noselect (concat (file-name-as-directory org-journal-dir) file)) (buffer-string)))) (insert file-string)))) ;(display-buffer (current-buffer)) (write-file (concat (file-name-as-directory org-journal-dir) "old-journal.org")))
in which org-journal-dir
is the path to my journal files.
To preview the output first, I use the display-buffer
line and annotate the write-file
line.
Then I encrypt the output file with gpg
(either in command line or with epa-encrypt-file
in Emacs) and delete the .org
file.
5. Avoiding entering passphrase each time I open my journal
The last issue I encountered (on one of my machine) is that I have to enter my passpharase each time I open my journal. I would like it to be cached for, say, an hour. The way to do it is to configure the GPG Agent, which ships with GPG. First is to see if any config already exists:
cd ~/.gnupg touch gpg-agent.conf cat gpg-agent.conf
Second, modify or type in these lines in the config file:
default-cache-ttl 3600 max-cache-ttl 86400
This will allow GPG Agent to cache my passphrase for 3600 seconds (one hour).
That’s it! Happy new year!
Footnotes:
see the FAQ of the Openkeychain website for why.