0

I need to generate quite a lot of gpg-keys for different tasks on my Debian Bullseye (Stable) machine. Also I want the highest level of security while being able to automate as much as possible.

Therefore I wrote a bash-script with the following features:

  • test if needed software is installed
  • use of xkcdpass for inspiration for the passphrase
  • create temporary working directory at /dev/shm for files export
  • create keys with the following options
    • Key-Type: eddsa
    • Key-Curve: Ed25519
    • Key-Usage: sign
    • Subkey-Type: ecdh
    • Subkey-Curve: Curve25519
    • Subkey-Usage: encrypt
    • Expire-Date: 1y
  • add additional signing key
  • export everything to temporary directory
  • delete primary key, only re-import subkeys
  • copy everything to a 'real' (non-temporary) directory (optional, could also be copied manually to e.g. a Keepass-database).

The script is the following:

#!/usr/bin/env bash

## ## enable bash stict mode
set -euo pipefail
trap 's=$?; echo "$0: Error on line "$LINENO": $BASH_COMMAND"; exit $s' ERR
IFS=$'\n\t'
# set -x  # disable after debugging



## ## test if all needed dependencies are available
command -v mktemp   >/dev/null 2>&1 || { echo >&2 "coreutils   are required but it's not installed.  Aborting."; exit 1; }
command -v gpg      >/dev/null 2>&1 || { echo >&2 "gpg          is required but it's not installed.  Aborting."; exit 1; }
command -v xkcdpass >/dev/null 2>&1 || { echo >&2 "xkcdpass     is required but it's not installed.  Aborting."; exit 1; }



## ## introduction
echo -e "## This script generates a gpg-keypair ========================================"
echo -e "\n"
echo -e "Several things are noteworthy:"
echo -e "    * besides the name, the password and the default key for the encryption,"
echo -e "      everything has defaults"
echo -e "    * files will be stored in a new, temporary directory at /dev/shm"
echo -e "    * a directory for the encrypted files will be generated at the pwd"
echo -e "    * files will be transferred back from the temporary to the finally used wd"
echo -e "\n"
echo -e "This script will copy the files in the end back to the pwd you started with"
echo -e "If you don't want this, please disable the last step so everything is in /dev/shm"
echo -e "\n"
echo -e "Already think about a passphrases!"
echo -e "Below you find some example sentences"
echo -e "\n"
xkcdpass -c 5
echo -e "\n"
echo -e "Also keep in mind, numbers and special characters are your friend!"
echo -e "\n"
echo -e "And obviously, don't use spaces for filenames or names!"
echo -e "\n"
echo -e "\n"


## ## store variables needed for later
echo -e "## variable definitions -------------------------------------------------------"
var_pwd="$(command pwd)"
echo -e "the current working directory is ${var_pwd}"
echo -e "\n"
var_tempwd="$(command mktemp -d -p /dev/shm/)"
echo -e "the working directory for the new files is ${var_tempwd}"
echo -e "\n"
echo -e "## what is the TYPE of the keyfile (e.g. 'EMAIL', 'PROJECT', ...)?"
read var_type
echo -e "the TYPE of the keyfile is $var_type"
echo -e "\n"
echo -e "## what is the NAME of the keyfile (e.g. 'user42', 'analysis17', ...)?"
read var_name
echo -e "the NAME of the keyfile user is $var_name"
echo -e "\n"
echo -e "## what is the LOCATION of the keyfile (e.g. 'server3', 'account7', ...)?"
read var_loc
echo -e "the LOCATION for the keyfile user is $var_loc"
echo -e "\n"
id_for_key="${var_name}@${var_loc}"
basename="key_${var_type}_${id_for_key}"
echo -e "the base name selected will be ${basename}"
echo -e "\n"
echo -e "## what is the real name you want to use for the key (e.g."
echo -e "'Alice Teller', 'Bob the Listener', 'Eve the Dropper')?"
read name_for_key
echo -e "the real name for the keyfile is ${name_for_key}"
echo -e "\n"
echo -e "\n"


## ## create new directories to work in
echo -e "## create directories ---------------------------------------------------------"
mkdir -p "${var_pwd}/${basename}"
echo -e "new directory created at ${var_pwd}/${basename}"
echo -e "\n"
cd "${var_tempwd}"
echo -e "switched to temporary directory at ${var_tempwd}"
echo -e "\n"
echo -e "the present working directory is $(command pwd)"
echo -e "\n"
echo -e "\n"


## ## create gpg-key
echo -e "## create gpg-key -------------------------------------------------------------"
gpg --batch --full-gen-key <<EOF
Key-Type: eddsa 
Key-Curve: Ed25519 
Key-Usage: sign 
Subkey-Type: ecdh
Subkey-Curve: Curve25519
Subkey-Usage: encrypt
Name-Real: $name_for_key
Name-Email: $id_for_key
Expire-Date: 1y
EOF


## ## perform changes to the gpg-key so that it can be used without the secret signing key
echo -e "## change gpg-key -------------------------------------------------------------"
## update main key (add subkey for signing)
echo -e "update main key (add subkey for signing)"
gpg --batch --quick-add-key $(gpg --list-options show-only-fpr-mbox --list-secret-keys | grep ${id_for_key} | awk '{print $1}') ed25519 sign 1y
echo -e "\n"

## export keys to local folder
echo -e "export keys to local folder ${var_tempwd}/"
gpg --export $(gpg --list-options show-only-fpr-mbox --list-secret-keys | grep ${id_for_key} | awk '{print $1}')  > ${var_tempwd}/gpg-public-${basename}.pub
gpg --armor --export-secret-keys $(gpg --list-options show-only-fpr-mbox --list-secret-keys | grep ${id_for_key} | awk '{print $1}')  > ${var_tempwd}/gpg-private-full-${basename}.asc
gpg --armor --output ${var_tempwd}/gpg-private-sub${basename}.asc --export-secret-subkeys $(gpg --list-options show-only-fpr-mbox --list-secret-keys | grep ${id_for_key} | awk '{print $1}') 
echo -e "\n"

## delete keys stored in $HOME/.gnupg
echo -e "delete keys stored in $HOME/.gnupg"
gpg --delete-secret-and-public-keys $(gpg --list-options show-only-fpr-mbox --list-secret-keys | grep ${id_for_key} | awk '{print $1}') 
echo -e "\n"

## re-import subkeys
echo -e "re-import subkeys"
echo -e "disabled, please perform this step manually to test if everything works"
# gpg --import ${var_tempwd}/gpg-private-sub${basename}.asc ${var_tempwd}/gpg-public-${basename}.pub
echo -e "\n"
echo -e "\n"


## ## finish
echo -e "## finishing up ---------------------------------------------------------------"
echo -e "encrypted keys moved to non-temporary directory"
echo -e "don't forget to back them up!"
mv ${var_tempwd}/gpg-* "${var_pwd}/${basename}"
echo -e "\n"
echo -e "\n"


echo -e "## ============================================================================"
echo -e "creation of gpg-keys ${var_type}_${id_for_key} finished at $(date)"
echo -e "## ============================================================================"
echo -e "\n"
echo -e "\n"

But I'm unsure if, from a security point of view, I should change anything since I'm not that experiences with bash-scripts.

Any recommendations? Is my approach preferable to the one mentioned e.g. here or here?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.