Instructions largely found from here: https://www.esev.com/blog/post/2015-01-pgp-ssh-key-on-yubikey-neo/ https://www.ahrenstein.com/blog/using-a-yubikey-4-and-gpg-for-ssh-on-a-mac/
brew install gnupg2 pinentry-mac
brew install --cask gpg-suite
brew install ykman
Best to store master key and backups on an encrypted removable drive. I formatted a USB drive for this purpose.
1. Mount the encrypted USB drive and link it in to the default .gnupg directory (this will create a new keyring on your encrypted drive)
mv .gnupg .gnupg.orig
ln -s /media/USB .gnupg
gpg --expert --full-generate-key
Select Option 8 - RSA (set your own capabilities)
Toggle sign, encrypt, authenticate to "off"
4096 RSA
Expire 1y
gpg --list-secret-keys --keyid-format=long
You'll see output like the following:
-------------------------------
sec ed25519/A9C4550328B2FA3C 2023-01-06 [SC]
048282B36C1D7502380C5E8FB9F3220428C2EA3C
uid [ultimate] Your Name <[email protected]>
ssb cv25519/6CD2394A1E1F4C10 2023-01-06 [E]
The Key ID is the value after the 40 bit key just above the line starting with uid, so in this case it is 048282B36C1D7502380C5E8FB9F3220428C2EA3C. We'll need that again later so we'll temporarily stash it into an environment variable:
export KEY_ID="your-key-id-here"
export GPG_BACKUP_FOLDER="/Volumes/FastSSD/gpgKeys"
gpg --gen-revoke $KEY_ID > $GPG_BACKUP_FOLDER/$KEY_ID-revocation-certificate.asc
gpg --edit-key $KEY_ID
addkey
option 8
(S) Toggle the sign capability off
(Q) Finished
follow prompts
addkey
option 8
(E) Toggle the encrypt capability off
(Q) Finished
follow prompts
addkey
option 8
(S) Toggle the sign capability off
(E) Toggle the encrypt capability off
(A) Toggle the authenticate capability on
(Q) Finished
follow prompts
save
gpg --armor --export-secret-keys $KEY_ID > $GPG_BACKUP_FOLDER/$KEY_ID-secret.asc
gpg --armor --export-secret-subkeys $KEY_ID > $GPG_BACKUP_FOLDER/$KEY_ID-sub-keys.asc
gpg --armor --export $KEY_ID > $GPG_BACKUP_FOLDER/$KEY_ID-public.asc
ykman openpgp reset
Note the default pin values, you will need it in the next steps.
ykman openpgp access change-admin-pin
ykman openpgp access change-pin
ykman openpgp keys set-touch aut off
ykman openpgp keys set-touch sig on
ykman openpgp keys set-touch enc on
gpg --delete-secret-key $KEY_ID
gpg --delete-keys $KEY_ID
gpg --import < $GPG_BACKUP_FOLDER/$KEY_ID-secret.asc
gpg --import < $GPG_BACKUP_FOLDER/$KEY_ID-sub-keys.asc
gpg --edit-key $KEY_ID
key 1
keytocard
(2) Encryption key
key 1
key 2
keytocard
(1) Signature key
key 2
key 3
keytocard
(3) Authentication key
save
In this step we will add the location of your public key to the YubiKey. This location will be configured later in this Gist. [Save and Distribute the public PGP Key](# Save and Distribute the public PGP Key)
gpg --card-edit
admin #become admin
forcesig #make sure the pin is entered before signing
url
URL to retrieve public key: https://keys.openpgp.org/vks/v1/by-fingerprint/$KEY_ID
quit
5. Remove your yubikey - insert next key and repeat from step 1
When the master key was created, and each time a subkey was created, a public and private RSA key was also generated. The private keys should remain on the USB drive and on the Yubikey.
The public keys should be distributed to a location where others can find it. Use a public keyserver.
Once a location has been chosen, it’s a good idea to embed the location into the PGP key. That way users know where to find the version of the key with the most up-to-date signatures, subkeys, and revocations. GnuPG can also automatically fetch the latest version of the key with –refresh-keys if the location is embedded within the key. The keyserver command embeds a URL to this key within the public PGP key.
gpg --edit-key <$KEY_ID
keyserver hkps://keys.openpgp.org
showpref
save
# upload it to a keyserver
gpg --keyserver hkps://keys.openpgp.org --send-key $KEY_ID
- Remove the USB drive with the master key and re-enable your local pgp keyring
# Remove the symlink pointing to /media/USB
rm .gnupg
# Replace the original directory
mv .gnupg.orig .gnupg
- Verify that the master key is no longer on the keyring (it’s on the USB drive’s keyring!)
gpg -K
make sure there is a # after sec, should look like:
sec# rsa4096 2023-08-11 [CA]
cat << EOF > ~/.gnupg/gpg-agent.conf
default-cache-ttl-ssh 3600
max-cache-ttl 7200
max-cache-ttl-ssh 7200
enable-ssh-support
EOF
cat << EOF > ~/.gnupg/gpg.conf
auto-key-retrieve
no-emit-version
default-key $KEY_ID
EOF
cat << EOF >> ~/.zshrc
## Enable GPG SSH capability
export GPG_TTY=$(tty)
export SSH_AUTH_SOCK=${HOME}/.gnupg/S.gpg-agent.ssh
alias gpgreset='gpg-connect-agent killagent /bye; gpg-connect-agent updatestartuptty /bye; gpg-connect-agent /bye'
function switchyubi() {
rm -r ~/.gnupg/private-keys-v1.d
gpgconf --kill gpg-agent
gpg --card-status
}
EOF
source ~/.zshrc
ps -ef | grep gpg
501 6826 1 0 Sat09AM ?? 0:04.59 gpg-agent --homedir /Users/jeffbarrows/.gnupg --enable-ssh-support --daemon
git config --global commit.gpgsign true
git config --global user.signingkey $KEY_ID
Upload your public key to your github account
- Check the Yubikey
$ gpg --card-status
Reader ...........: Yubico Yubikey 4 OTP U2F CCID
Application ID ...: D2760001240102010006061088330000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 06108833
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : https://pgp.mit.edu/pks/lookup?op=get&search=0x5488D417D56272B8
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: rsa4096 rsa2048 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 31
Signature key ....: 658B 9632 75E1 C826 2D1C D3FD 7C31 8499 05FB 50B0
created ....: 2018-01-05 04:43:10
Encryption key....: A238 5DBB 4B58 0BC8 8460 F170 DDDE AF66 DABF 6872
created ....: 2018-01-05 04:18:17
Authentication key: ECAB 7100 6253 9826 9C51 FD4B 6DF8 0B9B 3DC7 45F2
created ....: 2018-01-05 04:46:31
General key info..: sub rsa4096/7C31849905FB50B0 2018-01-05 Jeff Barrows <[email protected]>
sec# rsa4096/5488D417D56272B8 created: 2018-01-05 expires: 2019-01-05
ssb> rsa2048/DDDEAF66DABF6872 created: 2018-01-05 expires: 2019-01-05
card-no: 0006 06108833
ssb> rsa4096/7C31849905FB50B0 created: 2018-01-05 expires: 2019-01-05
card-no: 0006 06108833
ssb> rsa4096/6DF80B9B3DC745F2 created: 2018-01-05 expires: 2019-01-05
card-no: 0006 06108833
echo "$(uname -a)" | gpg --encrypt --armor --recipient $KEY_ID
-----BEGIN PGP MESSAGE-----
hQEMA93er2bav2hyAQf/cZGuS56Jd87ohNIcAComLGdQ8i1+VR6UMz0ueuVYx+lO
cmw4AhiebDrwHz+Lwk4ZcL8C4TluU1kU1wcwaAEQEfZgw8YNV5uijyVOwgX41KfK
b0nrLoG3AHOGhIQUA8MagzETGu9DPikV1J10SCLErrQsBdzsWWjJsnvfiUG+51Rn
Ltns+gWwygidmEwRnqwBKZNz2xX0oAWw+TluHbykcCkuTP8Hn4FR2LfVSOrA6DM2
8LxtvKdBv8FFxw1m6oGTXXA1WjUWbTHUOYKEZdxMmcvQ2lbIQ/3f3jCxV6ltBcTm
uuSBCYerls5JD1eJtLrqG0W7LOeqrjAc7c5m//TYMtK0AaLf1VSw7I8hCUJMnMQs
MjkSbG6NIvhCJvgel4FExVACNTnfIw3r0j3tD9uPJ2U7v6R/s6fMvYdhjseTsguv
uokrRbBFcUASQzfVSogOSTmhiPIhGTayIvrz5oieYvnOEWkrVHmKZHgoivE7lD92
ENGaWuLwXqJpxN3KZ/+0Q6WpFaIpq9epYDaAOcV0UwHz5Jm6OJlOsFu44Wde0uQ5
5ncUq7mA9VhXyJM16wic50xa1SnB
=S0yp
-----END PGP MESSAGE-----
- You should get prompted for your yubikey pin so it can read the key
$ echo "$(uname -a)" | gpg --armor --clearsign --default-key $KEY_ID
gpg: using "0BDD08F0F38CE51DBD78EBDD33C2B6D2715D4FA8" as default secret key for signing
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA256
Darwin Linos-Mac-Studio.local 22.6.0 Darwin Kernel Version 22.6.0: Wed Jul 5 22:22:05 PDT 2023; root:xnu-8796.141.3~6/RELEASE_ARM64_T6000 arm64
-----BEGIN PGP SIGNATURE-----
iQEzBAEBCAAdFiEE6WF7cvUnHvex2oooJkKUg3wGL9MFAmTXlDoACgkQJkKUg3wG
L9Pxngf/QAT8uZbHknZXu16ETFt6Iiq/26vPhh39HYMhDVZl8juWkMSl3XiGjY8s
lyUyyVhQ2kUazygtR2OFVHH69oE06n9rOkjWpDqAALxTvVXP9oXR7mfWM/Ed8up2
nGVtXSGtzVnIQA21L/eYAkluBOiCI8u3i5GGLxPqUS2Z9YEso/PfLx45/Xvh4XW1
QSMe8t7iWjJl+JVlkaW8MNvnIUSpxlt34m1NAGgzbiSA+cd2pp1xOAbN2fles1ul
Lpi/GxFcuiuviJr7G9IUJii9I9pMLhfONoj+g200L2M1g4aLXz8ybfh9SaW8fUq9
JYe91c2Lr45HIfoYPqrCc69arxVf6w==
=rIMy
-----END PGP SIGNATURE-----
- When you
git commit -am "Foo"
you should get prompted for your Yubikey PIN - Looking at your commit history in github should show 'verified'
- $ git log --show-signature
commit 9686ff87cc398689b08c3084e180d8cdb75888aa (HEAD -> master)
gpg: Signature made Sun Jan 7 10:18:06 2018 PST
gpg: using RSA key 658B963275E1C8262D1CD3FD7C31849905FB50B0
gpg: issuer "[email protected]"
gpg: Good signature from "Jeff Barrows <[email protected]>" [ultimate]
Author: Jeff Barrows <[email protected]>
Date: Sun Jan 7 10:18:06 2018 -0800
Update