Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Generate a GPG key suitable for an OpenPGP smartcard or YubiKey device (utilizing three slots and all four capabilities)
# script generates a GPG master key with Certify+Sign capabilities, and two subkeys each possessing the Encrypt and Authenticate capabilities.
# intended to fill the 3 slots on a YubiKey <> or OpenPGP card <>
# allows selection of variables via a single dependency besides GnuPG 2.x: dialog
# kevin gallagher (@ageis) <>
function gen_smartcard_key() {
local GPG_KEY_CREATION_DATE="$(date +%Y-%m-%d)"
if [[ -z "${GNUPGHOME}" ]]; then
exec 4>&1;
export GNUPGHOME=$(dialog --inputbox 'Confirm your GNUPGHOME:' 0 0 "${HOME}/.gnupg" 2>&1 1>&4)
exec 4>&-;
echo -e "GNUPGHOME is ${GNUPGHOME}\n"
exec 5>&1;
local GPG_KEY_PASSWORD=$(dialog --passwordbox 'Password:' 0 0 2>&1 1>&5);
exec 5>&-;
exec 6>&1;
local GPG_KEY_NAME=$(dialog --inputbox 'Name:' 0 0 2>&1 1>&6);
exec 6>&-;
exec 7>&1;
local GPG_KEY_EMAIL=$(dialog --inputbox 'E-mail:' 0 0 2>&1 1>&7);
exec 7>&-;
exec 8>&1;
local GPG_KEY_EXPIRY=$(dialog --inputbox 'Expiry:' 0 0 '5y' 2>&1 1>&8);
exec 8>&-;
local DIALOG_RESULT=$(mktemp 2>/dev/null)
# trap "rm -f ${DIALOG_RESULT}" 0 1 2 5 15
local GPG_KEY_SIZE=$(whiptail --title "GPG key size" --radiolist "Choose:" 12 40 4 \
1 "1024" off \
2 "2048" off \
3 "3072" off \
4 "4096" on 3>&1 1>&2 2>&3)
case $(echo ${GPG_KEY_SIZE}) in
1) local GPG_KEY_LENGTH=1024;;
2) local GPG_KEY_LENGTH=2048;;
3) local GPG_KEY_LENGTH=3072;;
4) local GPG_KEY_LENGTH=4096;;
echo -e "We'll generate a cert+sign primary key with the following parameters:\n"
echo -e "Key-Type: ${GPG_KEY_ALGO}\n"
echo -e "Key-Length: ${GPG_KEY_LENGTH}\n"
echo -e "Name-Real: ${GPG_KEY_NAME}\n"
echo -e "Name-Email: ${GPG_KEY_EMAIL}\n"
echo -e "Expire-Date: ${GPG_KEY_EXPIRY}\n"
echo -e "Passphrase: ${GPG_KEY_PASSWORD}\n"
echo -e "Creation-Date: ${GPG_KEY_CREATION_DATE}\n"
export GPG_PARAM_FILE="$(mktemp)"
export GPG_KEY_TEMP_ALIAS=$(basename "${GPG_PARAM_FILE}" | cut -d'.' -f2)
cat << EOF > "${GPG_PARAM_FILE}"
%echo Generating a GPG key...
Key-Type: ${GPG_KEY_ALGO}
Key-Length: ${GPG_KEY_LENGTH}
Key-Usage: cert,sign
Name-Real: ${GPG_KEY_NAME}
Name-Email: ${GPG_KEY_EMAIL}
Expire-Date: ${GPG_KEY_EXPIRY}
Passphrase: ${GPG_KEY_PASSWORD}
%echo Done
export GPG_FINGERPRINT=$(gpg --homedir "${GNUPGHOME}" --verbose --batch --status-fd=1 --generate-key "${GPG_PARAM_FILE}" | cut -d' ' -f4)
gpg --import "${GNUPGHOME}/${GPG_KEY_TEMP_ALIAS}.pub"
gpg --import "${GNUPGHOME}/.gnupg/private-keys-v1.d/${GPG_FINGERPRINT}.key"
for cap in encrypt auth; do
echo -e "Generating $cap key for ${GPG_FINGERPRINT}...\n"
gpg --homedir "${GNUPGHOME}" --verbose --batch --quick-add-key ${GPG_FINGERPRINT} ${GPG_KEY_ALGO}${GPG_KEY_LENGTH} $cap ${GPG_KEY_EXPIRY}
echo -e "Setting your new key to ultimately trusted...\n"
gpg --homedir "${GNUPGHOME}" --verbose --yes --list-keys --fingerprint --with-colons "${GPG_FINGERPRINT}" |
sed -E -n -e 's/^fpr:::::::::([0-9A-F]+):$/\1:6:/p' |
gpg --homedir "${GNUPGHOME}" --verbose --import-ownertrust --yes

This comment has been minimized.

Copy link

@xslim xslim commented Oct 21, 2019

Are you using this in a Docker?
which docker image you are using and how do you connect yubikey to it?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.