Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- set -euo pipefail
- GNUPGHOME=$(mktemp -d)
- cleanup() {
- echo rm -rf "$GNUPGHOME"
- killall gpg-agent || :
- }
- trap cleanup EXIT
- echo "Killing any gpg-agent processes"
- killall gpg-agent || :
- export GNUPGHOME
- if [ -z "${GIVENNAME:-}" ]; then
- echo -n "Enter your given name: "
- read -r GIVENNAME
- fi
- if [ -z "${SURNAME:-}" ]; then
- echo -n "Enter your surname: "
- read -r SURNAME
- fi
- if [ -z "${EMAILADDRESS:-}" ]; then
- echo -n "Enter your email address: "
- read -r EMAILADDRESS
- fi
- if [ -z "${KEYSIZE:-}" ]; then
- echo -n "Enter your desired key size (2048 for Yubikey NEO, 4096 otherwise): "
- read -r KEYSIZE
- fi
- if [ -z "${USER_PIN:-}" ]; then
- echo -n "Choose a user PIN (6-127 chars). You will use this a lot: "
- read -r USER_PIN
- fi
- if [ -z "${ADMIN_PIN:-}" ]; then
- echo -n "Choose an admin PIN (8-127 chars). Used (hopefully rarely) for unlocking the user PIN: "
- read -r ADMIN_PIN
- fi
- KEYCOMMENT="Yubikey $(gdate +%Y%m%d)"
- cat << EOF > "$GNUPGHOME/gpg.conf"
- use-agent
- personal-cipher-preferences AES256 AES192 AES CAST5
- personal-digest-preferences SHA512 SHA384 SHA256 SHA224
- default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
- cert-digest-algo SHA512
- s2k-digest-algo SHA512
- s2k-cipher-algo AES256
- charset utf-8
- fixed-list-mode
- no-comments
- no-emit-version
- keyid-format 0xlong
- list-options show-uid-validity
- verify-options show-uid-validity
- with-fingerprint
- EOF
- cat << EOF > "$GNUPGHOME/gpg-agent.conf"
- pinentry-program /usr/local/bin/pinentry-tty
- default-cache-ttl 60
- max-cache-ttl 120
- EOF
- echo | REALNAME="$GIVENNAME $SURNAME" EMAILADDRESS=$EMAILADDRESS KEYSIZE=$KEYSIZE KEYCOMMENT=$KEYCOMMENT expect <<"EOF"
- set realname $env(REALNAME)
- set email $env(EMAILADDRESS)
- set comment $env(KEYCOMMENT)
- set keysize $env(KEYSIZE)
- set timeout 1
- spawn gpg --full-generate-key
- expect "(4) RSA (sign only)"
- expect "Your selection?"
- send "4\r"
- expect "What keysize do you want? (2048)"
- send "$keysize\r"
- expect "Key is valid for?"
- send "0\r"
- expect "Is this correct? (y/N)"
- send "y\r"
- expect "Real name: "
- send "$realname\r"
- expect "Email address: "
- send "$email\r"
- expect "Comment: "
- send "$comment\r"
- expect "Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit?"
- send "O\r"
- expect "Please enter the passphrase to"
- expect "Passphrase:"
- sleep 0.5
- send "\r"
- expect "Repeat:"
- sleep 0.5
- send "\r"
- expect "You have not entered a passphrase - this is in general a bad idea!"
- expect "Please confirm that you do not want to have any protection on your key"
- expect "es, protection is not needed"
- sleep 0.5
- set timeout 20
- send "y"
- expect "public and secret key created and signed"
- expect "pub rsa$keysize"
- set timeout 1
- wait
- EOF
- echo "Keys generated!"
- KEYID=$(gpg --list-keys|sed -ne '/Key fingerprint =/s/Key fingerprint =//p'|tr -d \ )
- echo "Key ID is $KEYID"
- echo | KEYID=$KEYID KEYSIZE=$KEYSIZE expect <<"EOF"
- set keyid $env(KEYID)
- set keysize $env(KEYSIZE)
- set timeout 1
- spawn gpg --expert --edit-key $keyid
- expect "gpg>"
- send "addkey\r"
- expect "(4) RSA (sign only)"
- send "4\r"
- expect "What keysize do you want?"
- send "$keysize\r"
- expect "Key is valid for?"
- send "0\r"
- expect "Is this correct? (y/N)"
- send "y\r"
- expect "Really create? (y/N)"
- send "y\r"
- expect "Please enter the passphrase to"
- expect "Passphrase:"
- sleep 0.5
- send "\r"
- expect "Repeat:"
- sleep 0.5
- send "\r"
- expect "You have not entered a passphrase - this is in general a bad idea!"
- expect "Please confirm that you do not want to have any protection on your key"
- expect "es, protection is not needed"
- sleep 0.5
- set timeout 20
- send "y"
- expect "ssb rsa$keysize"
- set timeout 1
- expect "usage: S"
- expect "gpg>"
- send "addkey\r"
- expect "(6) RSA (encrypt only)"
- send "6\r"
- expect "What keysize do you want?"
- send "$keysize\r"
- expect "Key is valid for?"
- send "0\r"
- expect "Is this correct? (y/N)"
- send "y\r"
- expect "Really create? (y/N)"
- send "y\r"
- expect "Please enter the passphrase to"
- expect "Passphrase:"
- sleep 0.5
- send "\r"
- expect "Repeat:"
- sleep 0.5
- send "\r"
- expect "You have not entered a passphrase - this is in general a bad idea!"
- expect "Please confirm that you do not want to have any protection on your key"
- expect "es, protection is not needed"
- sleep 0.5
- set timeout 20
- send "y"
- expect "ssb rsa$keysize"
- set timeout 1
- expect "usage: E"
- expect "gpg>"
- send "addkey\r"
- expect "(8) RSA (set your own capabilities)"
- send "8\r"
- expect "Current allowed actions: Sign Encrypt"
- expect "(S) Toggle the sign capability"
- expect "Your selection?"
- send "S\r"
- expect "Current allowed actions: Encrypt"
- expect "(E) Toggle the encrypt capability"
- expect "Your selection?"
- send "E\r"
- expect "Current allowed actions:"
- expect "(A) Toggle the authenticate capability"
- expect "Your selection?"
- send "A\r"
- expect "Current allowed actions: Authenticate"
- expect "(Q) Finished"
- expect "Your selection?"
- send "Q\r"
- expect "What keysize do you want?"
- send "$keysize\r"
- expect "Key is valid for?"
- send "0\r"
- expect "Is this correct? (y/N)"
- send "y\r"
- expect "Really create? (y/N)"
- send "y\r"
- expect "Please enter the passphrase to"
- expect "Passphrase:"
- sleep 0.5
- send "\r"
- expect "Repeat:"
- sleep 0.5
- send "\r"
- expect "You have not entered a passphrase - this is in general a bad idea!"
- expect "Please confirm that you do not want to have any protection on your key"
- expect "es, protection is not needed"
- sleep 0.5
- set timeout 20
- send "y"
- expect "gpg> "
- set timeout 1
- send "save\r"
- sleep 3
- EOF
- echo
- echo "Running hokey against the generated keys to check they are OK"
- echo "It won't like the fact that our keys don't expire, but you can ignore that"
- echo "It also won't like the lack of cross-certification for the authentication key but this is a false alarm"
- gpg --export "$KEYID" | hokey lint
- echo -n "Does everything look OK? (y/n) "
- read -r yesno
- [ "$yesno" == y ] || exit 1
- echo -n "Insert your Yubikey and press enter"
- read -r
- if ! ykman mode | grep -qF 'Current connection mode is: OTP+FIDO+CCID'; then
- echo "You will need to say yes to the prompt from ykman"
- ykman mode OTP+FIDO+CCID
- fi
- echo | USER_PIN=$USER_PIN ADMIN_PIN=$ADMIN_PIN GIVENNAME=$GIVENNAME SURNAME=$SURNAME EMAILADDRESS=$EMAILADDRESS expect <<"EOF"
- set user_pin $env(USER_PIN)
- set admin_pin $env(ADMIN_PIN)
- set givenname $env(GIVENNAME)
- set surname $env(SURNAME)
- set email $env(EMAILADDRESS)
- set timeout 1
- spawn gpg --card-edit
- expect "gpg/card> "
- send "admin\r"
- expect "Admin commands are allowed"
- expect "gpg/card> "
- send "passwd\r"
- expect "3 - change Admin PIN"
- expect "Your selection? "
- send "3\r"
- expect "Please enter the Admin PIN"
- expect "Admin PIN: "
- sleep 0.5
- send "12345678\r"
- expect "New Admin PIN"
- expect "Admin PIN: "
- sleep 0.5
- send "$admin_pin\r"
- expect "Repeat this PIN"
- expect "Admin PIN: "
- sleep 0.5
- send "$admin_pin\r"
- expect "PIN changed."
- expect "1 - change PIN"
- expect "Your selection? "
- send "1\r"
- expect "Please enter the PIN"
- expect "PIN: "
- sleep 0.5
- send "123456\r"
- expect "New PIN"
- expect "PIN: "
- sleep 0.5
- send "$user_pin\r"
- expect "Repeat this PIN"
- expect "PIN: "
- sleep 0.5
- send "$user_pin\r"
- expect "PIN changed."
- expect "Q - quit"
- expect "Your selection? "
- send "Q\r"
- expect "gpg/card> "
- send "name\r"
- expect "Cardholder's surname:"
- send "$surname\r"
- expect "Cardholder's given name:"
- send "$givenname\r"
- expect "Please enter the Admin PIN"
- expect "Admin PIN: "
- sleep 0.5
- send "$admin_pin\r"
- expect "gpg/card>"
- send "lang\r"
- expect "Language preferences:"
- send "en\r"
- expect "gpg/card>"
- send "login\r"
- expect "Login data (account name):"
- send "$email\r"
- expect "gpg/card>"
- send "\r"
- expect "General key info"
- expect "gpg/card>"
- send "quit\r"
- sleep 3
- EOF
- echo | KEYSIZE=$KEYSIZE KEYID=$KEYID ADMIN_PIN=$ADMIN_PIN expect <<"EOF"
- set keysize $env(KEYSIZE)
- set keyid $env(KEYID)
- set admin_pin $env(ADMIN_PIN)
- set timeout 1
- spawn gpg --edit-key $keyid
- expect "ssb rsa$keysize"
- expect "gpg>"
- send "key 1\r"
- expect "ssb* rsa$keysize"
- expect "ssb rsa$keysize"
- expect "ssb rsa$keysize"
- expect "gpg>"
- send "keytocard\r"
- expect "Please select where to store the key:"
- expect "(1) Signature key"
- expect "Your selection?"
- send "1\r"
- expect "Please enter the Admin PIN"
- expect "Admin PIN: "
- sleep 0.5
- send "$admin_pin\r"
- expect "ssb* rsa$keysize"
- expect "ssb rsa$keysize"
- expect "ssb rsa$keysize"
- expect "gpg>"
- send "key 1\r"
- expect "ssb rsa$keysize"
- expect "ssb rsa$keysize"
- expect "ssb rsa$keysize"
- expect "gpg>"
- send "key 2\r"
- expect "ssb rsa$keysize"
- expect "ssb* rsa$keysize"
- expect "ssb rsa$keysize"
- expect "gpg>"
- send "keytocard\r"
- expect "Please select where to store the key:"
- expect "(2) Encryption key"
- expect "Your selection?"
- send "2\r"
- expect "Please enter the Admin PIN"
- expect "Admin PIN: "
- sleep 0.5
- send "$admin_pin\r"
- expect "ssb rsa$keysize"
- expect "ssb* rsa$keysize"
- expect "ssb rsa$keysize"
- expect "gpg>"
- send "key 2\r"
- expect "ssb rsa$keysize"
- expect "ssb rsa$keysize"
- expect "ssb rsa$keysize"
- expect "gpg>"
- send "key 3\r"
- expect "ssb rsa$keysize"
- expect "ssb rsa$keysize"
- expect "ssb* rsa$keysize"
- expect "gpg>"
- send "keytocard\r"
- expect "Please select where to store the key:"
- expect "(3) Authentication key"
- expect "Your selection?"
- send "3\r"
- expect "Please enter the Admin PIN"
- expect "Admin PIN: "
- sleep 0.5
- send "$admin_pin\r"
- expect "ssb rsa$keysize"
- expect "ssb rsa$keysize"
- expect "ssb* rsa$keysize"
- expect "gpg>"
- send "save\r"
- sleep 3
- EOF
- if [ "$(gpg --list-secret-keys | grep -c '^ssb>')" -ne 3 ]; then
- echo "Unexpected output from 'gpg --list-secret-keys':"
- gpg --list-secret-keys
- exit 1
- fi
- gpg --armor --export "$KEYID" > ~/"gpg-$KEYID.txt"
- echo "Exported public key to ~/gpg-$KEYID.txt"
- echo "Sending key to keyserver"
- if ! gpg --send-key "$KEYID"; then
- echo "WARNING: Failed to send key to keyserver - run gpg --send-key $KEYID manually" >&2
- fi
- GNUPGHOME= gpg --import ~/"gpg-$KEYID.txt"
- echo "Killing any gpg-agent processes"
- killall gpg-agent || :
- echo -n "Unplug your Yubkey, re-insert it and press Enter"
- read -r
- [ ! -f ~/.gnupg/gpg.conf ] || mv -v ~/.gnupg/gpg.conf ~/.gnupg/gpg.conf.$(gdate +%s)
- echo "Generating new ~/.gnupg/gpg.conf"
- restore_umask=$(umask -p)
- umask=077
- cat << EOF > ~/.gnupg/gpg.conf
- auto-key-locate keyserver
- keyserver hkps://hkps.pool.sks-keyservers.net
- keyserver-options no-honor-keyserver-url
- personal-cipher-preferences AES256 AES192 AES CAST5
- personal-digest-preferences SHA512 SHA384 SHA256 SHA224
- default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
- cert-digest-algo SHA512
- s2k-cipher-algo AES256
- s2k-digest-algo SHA512
- charset utf-8
- fixed-list-mode
- no-comments
- no-emit-version
- keyid-format 0xlong
- list-options show-uid-validity
- verify-options show-uid-validity
- with-fingerprint
- use-agent
- require-cross-certification
- EOF
- $restore_umask
- [ ! -f ~/.gnupg/gpg-agent.conf ] || mv -v ~/.gnupg/gpg-agent.conf ~/.gnupg/gpg-agent.conf.$(gdate +%s)
- echo "Generating new ~/.gnupg/gpg-agent.conf"
- cat << EOF > ~/.gnupg/gpg-agent.conf
- enable-ssh-support
- pinentry-program /usr/local/bin/pinentry-mac
- default-cache-ttl 60
- max-cache-ttl 120
- EOF
- GNUPGHOME= gpg --card-status
- GNUPGHOME= gpg --list-secret-keys
- echo | KEYID=$KEYID expect <<"EOF"
- set keyid $env(KEYID)
- set timeout 1
- spawn gpg --edit-key $keyid
- expect "Secret key is available."
- expect "gpg>"
- send "trust\r"
- expect "Please decide how far you trust this user"
- expect "5 = I trust ultimately"
- expect "Your decision? "
- send "5\r"
- expect "Do you really want to set this key to ultimate trust? (y/N) "
- send "y\r"
- expect "trust: ultimate"
- expect "gpg>"
- send "quit\r"
- sleep 3
- EOF
Add Comment
Please, Sign In to add comment