July 10, 2020

Emacs, GnuPG and Pass

Intro

This post is the first out of two about GnuPG, password management, email, signing and encrypting emails and git commit signing. As always with a helping hand from Emacs. As the posts cover a lot of ground step by step instructions are not desirable. Links to more detailed resources can be found in each section. The main goal is to provide a quick but informative overview and give inspiration for further research.

The big picture is. Use GnuPG to generate asymmetric keys. Generate sub keys for encryption/decryption and signing. Sub keys have a lifetime of 1 year. After 1 year new sub keys for encrypt/decrypt and signing needs to be generated. Use signing sub key to sign git commits. Use encryption/decryption sub key to encrypt/decrypt password files in pass password store. Use Emacs for for gpg pinentry and install a Emacs mode to manage pass passwords.

This posts covers security, but the level of security discussed here can be increased further. Some weaknesses that the post don't cover is. Master key is not generated offline. Master key is not removed from keyring (more info). Public signing sub key is not published to key servers.

The layout of the post:

  • Environment; versions of the software.
  • GnuGP; how to generate keys and sub key, pinentry, backups.
  • Git; how to config git to sign with the gpg sub key.
  • Pass; init password store, some basic commands and a quick mention about browserpass.
  • Emacs pass mode; quick view of how to config Emacs to use it with pass.

If things are unclear, please contact me via twitter!

Environment

Version of the software in use.

Operating system

Arch Linux

#+BEGIN_SRC shell :results output code
  uname -a
#+END_SRC

#+RESULTS:
#+begin_src shell
Linux arch 5.7.7-arch1-1 #1 SMP PREEMPT Wed, 01 Jul 2020 14:53:16 +0000 x86_64 GNU/Linux
#+end_src

GnuPG

#+BEGIN_SRC shell :results output code
  gpg --version
#+END_SRC

#+RESULTS:
#+begin_src shell
gpg (GnuPG) 2.2.20
libgcrypt 1.8.5
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
#+end_src

Pass

#+BEGIN_SRC shell :results output code
  pass --version
#+END_SRC

#+RESULTS:
#+begin_src shell
============================================
= pass: the standard unix password manager =
=                                          =
=                  v1.7.3                  =
=                                          =
=             Jason A. Donenfeld           =
=               Jason@zx2c4.com            =
=                                          =
=      http://www.passwordstore.org/       =
============================================
#+end_src

Emacs

#+BEGIN_SRC shell :results output code
  emacs --version
#+END_SRC

#+RESULTS:
#+begin_src shell
GNU Emacs 26.3
Copyright (C) 2019 Free Software Foundation, Inc.
GNU Emacs comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of GNU Emacs
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING.
#+end_src

GnuPG

Intro

The first and most important part is GnuPG keys. They are used to encrypt, decrypt and for signing. This post will use one sub key for encryption/decryption and another for signing. The master key will never expire. The sub keys will have a lifetime of 1 year. After that they will be replaced with new sub keys.

This post wont cover the steps of publishing the public signing sub key. But one benefit of publishing new public keys "often" is the acknowledgment of new algorithms. If your published key is very old, it states that you only support old algorithms even if you run the latest GnuPG software. If you wanna know more about publishing keys, more info can be found here and here.

More details about GnuPG keys and sub keys can be found here:

Install

GnuPG on Arch. Together with gpg a collection of pinentry tools is installed.

pacman -S gnupg

Config files

Before start generating keys, make sure that you have this config file in place.

#+BEGIN_SRC shell :results output code
  cat ~/.gnupg/gpg.conf
#+END_SRC

#+RESULTS:
#+begin_src shell
personal-digest-preferences SHA256
cert-digest-algo SHA256
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
#+end_src

Create keys

Some of the steps are truncated with ... and some steps don't show exactly what you should do. If steps are confusing, turn to the links in the Intro section for guidance.

Start by creating a master key. This key should never expire and it's super important that you keep the master key safe. Bake sure to create a backup and store it offline.

gpg --full-gen-key
Select keys: RSA and RSA
Select keys size: 4096
Valid for: do not expire

Together with the master key, a sub key for encryption is also created. List the keys including sub key fingerprints.

gpg --list-secret-keys --with-subkey-fingerprint

Change the expire time of the encryption sub key to 1 year. This means that you every year need to generate a new encryption subkey from the master key.

gpg --edit-key <MASTER KEY FINGERPRINT>
key <EXISTING ENCRYPT SUB KEY FINGERPRINT>
expire
1y
...
save

Add sub key

This sub key will only be used for signing. After one year it will expire and a new one needs to be created from the master key.

gpg --edit-key <MASTER KEY FINGERPRINT>
addkey
Key:       RSA (sign only)
Key size:  4096
Valid for: 1y
...
save

Backup

Create backup and store some place safe!

umask 077; tar -cf $HOME/gnupg-backup.tar -C $HOME .gnupg

Pinentry

pinentry is the application that is responsible to ask you for the gpg passphrase. pinentry have applications for many environments. Such as curses, emacs, gnome, gtk, qt and tty. I am using pinentry-emacs. This requires some setup in order for Emacs to handle pinentry requests.

This is the gpg-agent config that tells it to use Emacs for pinentry:

#+BEGIN_SRC shell :results output code
  cat ~/.gnupg/gpg-agent.conf
#+END_SRC

#+RESULTS:
#+begin_src shell
default-cache-ttl 3600
allow-loopback-pinentry
pinentry-program /usr/bin/pinentry-emacs
allow-emacs-pinentry
#+end_src

When gpg need you to provide a passphrase to access gpg resources, it will ask in Emacs minibuffer!

Here is the list of pinentry applications provided by my current Arch GnuPG installation:

#+BEGIN_SRC shell :results output code
  pacman -Ql pinentry | awk '{ print $2}' | grep bin/pin
#+END_SRC

#+RESULTS:
#+begin_src shell
/usr/bin/pinentry
/usr/bin/pinentry-curses
/usr/bin/pinentry-emacs
/usr/bin/pinentry-gnome3
/usr/bin/pinentry-gtk-2
/usr/bin/pinentry-qt
/usr/bin/pinentry-tty
#+end_src

Emacs

I run Emacs in server mode and I always have an open Emacs session so when pinentry wants me to provide a passphrase, it does it through Emacs.

Here are the things related to run Emacs as server and to use the pinentry Emacs package.

#+BEGIN_SRC shell :results output code
  cat ~/.config/systemd/user/emacs.service
#+END_SRC

#+RESULTS:
#+begin_src shell
[Unit]
Description=Emacs text editor
Documentation=info:emacs man:emacs(1) https://gnu.org/software/emacs/

[Service]
Type=simple
ExecStart=/usr/bin/emacs --fg-daemon --debug-init
ExecStop=/usr/bin/emacsclient --eval "(kill-emacs)"
Environment=SSH_AUTH_SOCK=%t/keyring/ssh
Restart=on-failure

[Install]
WantedBy=default.target
#+end_src

#+BEGIN_SRC shell :results output code
  cat ~/.bin/start-emacs
#+END_SRC

#+RESULTS:
#+begin_src shell
#!/bin/bash
emacsclient -nc
#+end_src

#+BEGIN_SRC shell :results output code
  systemctl --user status emacs.service  # Service status
  systemctl --user enable emacs.service  # Start service on boot
  systemctl --user start emacs.service   # Start service
  systemctl --user stop emacs.service    # Stop service
  journalctl --user -u emacs.service     # Service stdout
#+END_SRC

#+BEGIN_SRC shell :results output code
  cat ~/.emacs.d/packages.el | awk 'NR==7,NR==11'
#+END_SRC

#+RESULTS:
#+begin_src shell
(use-package pinentry
  :pin melpa
  :config
  (setf epa-pinentry-mode 'loopback)
  (pinentry-start))
#+end_src

keys -> qr code

To get the keys to my phone I exported them from the keychain and into qr codes. Then used imagemagick to show each of them for some seconds before showing the next one. When key size is 4096 they don't fit into one qr image.

The qr codes can also be printed and kept in a safe as a secure backup.

mkdir -p /tmp/keys-export && cd $_
gpg --export-secret-keys --armor <SUB KEY FINGERPRINT> > sub.key
split -C 2500 sub.key splitkey-
for file in splitkey-??; do <"$file" qrencode -s 3 -d 150 -o "$file".qr; done
display -delay 50 *.qr
cd /tmp && rm -rf keys-export

Git

Now when there is a key to sign with it's time to configure git to use it.

First, get the fingerprint of your signing key.

gpg --list-secret-keys --with-subkey-fingerprint

Then tell git to gpg sign commits and what sub key fingerprint to use when doing so. It should be a '!' in the end of the fingerprint. It tells gpg that it's a sub key.

git config --global commit.gpgSign true
git config --global user.signingKey <SIGN SUBKEY FINGERPRINT>\!

Lets see how the git config looks like.

#+BEGIN_SRC shell :results output code
  cat ~/.gitconfig
#+END_SRC

#+RESULTS:
#+begin_src shell
[user]
        email = jherrlin@gmail.com
        name = John Herrlin
        signingKey = 6699DFA319365AAD1CE757040EE8540AE7F042B2!
[commit]
        gpgSign = true
#+end_src

Export your public sign sub key to provide it to a git hosting platform like GitHub or Bitbucket. Or to your colleagues.

gpg --export --armor 6699DFA319365AAD1CE757040EE8540AE7F042B2 > /tmp/public-sign.key

From now on all of your git commits are signed with your private sign sub key. Now people can be more ensured that it's you that made the change.

Pass

pass, "the standard unix password manager" is a nice way of managing passwords. It uses gpg encrypted files that are stored locally on your computer. As they are just files they can be version controlled and used in ways you are used to handle files. There are a couple of extensions to pass to make it interact with a web browser and for usage of your passwords on your mobile device. And of course there is a Emacs mode!

Here are a couple of resources for pass.

Install pass and browser extensions

On Arch, all of the packages are in the repo.

pacman -S pass browserpass browserpass-chromium

Init pass

Create a new store and provide your gpg id. Pass also have built in support for git.

pass init <ENCRYPT SUB KEY FINGERPRINT>!
pass git init

Insert new pass

Add a password to the password store.

pass insert fsf.org

Retrieve password

Get the password to stdout.

pass show fsf.org

More

pass have many more options, check them out.

pass --help

Browserpass

Install browser pass extension using the installation steps here.

Emacs pass mode

There is a good Emacs package calls pass. I use use-package to install it. To enter pass within Emacs use M-x pass.

#+BEGIN_SRC shell :results output code
  cat ~/.emacs.d/packages.el | awk 'NR==13,NR==16'
#+END_SRC

#+RESULTS:
#+begin_src shell
(use-package pass
  :pin melpa
  :config
  (setf epa-pinentry-mode 'loopback))
#+end_src

Powered by Hugo & Kiss.