This workflow provides configuration and shell commands for
working with GNU Privacy Guard(gpg), which implements
the Open PGP standard-RFC4880.
GNU Privacy Guard(GPG)
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))
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