simfish:

GNU Privacy Guard(GPG)

This workflow provides configuration and shell commands for working with GNU Privacy Guard(gpg), which implements the Open PGP standard-RFC4880.

cover image

Introduction

GPG is file encryption and signing tool.

Generate GPG Key: run gpg as shown below to start a key generation wizard:

  gpg --full-gen key

Export GPG Key: once a key is generated it should be backed up for using the --armor flag The --armor flag instructs gpg to use Armored ASCII format when exporting keys .

gpg --armor --export-secret-keys user@example.com >  ${HOME}/personal/user.sec

Where

  • user@example.com is either the user's email address as specified during key generation. Alternatively, it can be the users full name.
  • ${HOME}/personal/user.sec is file name where the private key is saved to.

Importing GPG from Backup: to import a key that has was priorly saved to, for example: ${HOME}/personal/user.sec run

gpg --import ${HOME}/personal/user.sec
gpg --edit-key "user@example.com"
# start an interactive session
gpg
> trust  # invoke trust subcommand
> 5      # response to trust level(ultimate)
> y      # confirmation (yes)

Emacs Integration

Configuration for gpg can be found under ~/.gnupg/gpg,

~/.gnupg/gpg.conf
~/.gnupg/gpg-agent.conf

gpg.conf file defaults are often fine, at least for my personal application. However, the gpg-agent.conf file contains the pin input prompt UI. In particular this config, epg-pinentry-mode.

For a smooth Emacs integration, set the option to loopback, which enables Emacs to prompt for pass-phrase using the mini-buffer instead of an external program.

# tell pinentry to allow features to divert the passphrase
# entry to a running Emacs instance
#allow-emacs-pinentry
pinentry-program /usr/bin/pinentry-gnome3

# allow clients to use the loopback pinentry features
allow-loopback-pinentry

For the changes to take effect run,

litdoc site gpg configure

This will execute a shell script shown below,

#!/usr/bin/env bash
source "${LITDOC_DIR}/libs/sh/lit-log.sh"

[ $# -ge 1 ] || {
    log_error "bad argument: $@"
    echo "usage: litdoc gpg configure"
    exit 1
}

gpg --version
gpgconf --reload gpg-agent
gpgconf --kill gpg-agent

Once a key is generated loading the built-in package epa is sufficient to encrypt and decrypt files with gpg extension. This also applies to encrypted elisp files with file extension *.el.gpg or header info:epa-file-encrypt-to header

# -*- epa-file-encrypt-to: ("user@example.com") -*-

Emacs command for creating and reading encrypted files is available too,

(defun gpg::new-encrypted-file(  )
  "Opens a new encrypted file"
  (interactive)
  (let ((buffer (generate-new-buffer "untitled")))
    (set-buffer-major-mode buffer)
    (with-current-buffer buffer
      (goto-char (point-max))
      (insert "# -*- epa-file-encrypt-to: (\"aronggile@gmail.com\") -*-"))
    (display-buffer buffer '(display-buffer-pop-up-frame . nil))))

Shell Integration

One useful application of gpg is to save sensitive information that needs to be passed on to applications, as encrypted shell environment files. And to decrypt and source the files on the fly at runtime. The following is a shell script for accomplishing that in a Bash shell,

bin/gpg_decrypt.sh

#! /usr/bin/env bash
#////////////////////////////////////////////////////
# main
#////////////////////////////////////////////////////
[ $# -eq 1 ] || {
    echo "ERROR: missing FILE argument"
    echo "usage: litdoc gpg -- FILE"
    exit 1
}

file="${1}"
[ -r "${file}" ] || {
    echo "[ERROR]: unable to read file: ${file}"
    exit 1
}


source <$(gpg --decrypt "${file}")

To run it use,

litdoc gpg decypt FILE # where FILE is encrypted

Packages

The entry point for this configuration is the GNU/Guix gnupg package. The package provides the command line application gpg. The additional package pinentry implements UI for securely prompting and reading pass-phrases.

(specifications->manifest '( "gnupg" "pinentry" "rng-tools" ))

When working within Emacs, the EasyPG Assistant(epg) package provides an elisp interface to gpg. Among other features, the interface implements automatic encryption and decryption of files with *.gpg extension.

(use-package epg
  :config
  (setq epa-file-encrypt-to '("aronggile@gmail.com"))
  (setq epg-pinentry-mode 'loopback))

References

Appendix: main(shell)

#! /usr/bin/env bash

source "${LITDOC_DIR}/libs/sh/log.sh"

[ $# -ge 1 ] || {
    echo "usage:"
    echo "litdoc gpg configure"
    echo "litdoc gpg decrypt FILE"
}

case ${1} in
    configure)
        shift
        exec "${LITDOC_SITEDIR}/bin/gpg_configure.sh" $@
        ;;
    decrypt)
       shift
        exec "${LITDOC_SITEDIR}/bin/gpg_decrypt.sh" $@
        ;;
    ,*)
        log_fail "[gpg]: bad argument: <${@}>"
        ;;
esac