This is my guide to using YubiKey as a SmartCard for storing GPG encryption, signing, and authentication keys. I have borrowed heavily (and in some cases copied directly) from drduh’s guide over on GitHub. I am documenting my journey because his instructions are very much multi-platform, and his also allow using the gpg keys for SSH, and that is not a primary concern of mine today (though I will probably go back and add that once I set it up.) I am distilling the instructions on his page to those that I needed to make things happen for me, on a Mac, and not using SSH. Because I used one year expirations for the sub-keys on the SmartCard, I will need to refer to portions of this again in a year.
Here we go
macOS: Download and install Homebrew and the following Brew packages:
brew install gnupg yubikey-personalization hopenpgp-tools ykman pinentry-mac
The first key to generate is the master key. It will be used for certification only - to issue subkeys that are used for encryption, signing and authentication. This master key should be kept offline at all times and only accessed to revoke or issue new subkeys.
Generate a new key with GPG, selecting (8) RSA (set your own capabilities)
, Certify
-only and 4096
bit keysize. Do not set the key to expire.
$ gpg --expert --full-generate-key
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(9) ECC and ECC
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(13) Existing key
Your selection? 8
Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Sign Certify Encrypt
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? E
Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Sign Certify
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? S
Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Certify
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? Q
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 0
Key does not expire at all
Is this correct? (y/N) y
GnuPG needs to construct a user ID to identify your key.
Real name: W. S. Wellington
Email address: my@email.com
Comment: [Optional - leave blank]
You selected this USER-ID:
"W. S> Wellington <my@email.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: /tmp.FLZC0xcM/trustdb.gpg: trustdb created
gpg: key 0x1A3FE8DD02C0515E marked as ultimately trusted
gpg: directory '/tmp.FLZC0xcM/openpgp-revocs.d' created
gpg: revocation certificate stored as '/tmp.FLZC0xcM/openpgp-revocs.d/578922058EED784920584DFA1A3FE8DD02C0515E.rev'
public and secret key created and signed.
Note that this key cannot be used for encryption. You may want to use
the command "--edit-key" to generate a subkey for this purpose.
pub rsa4096/0x1A3FE8DD02C0515E 2017-10-09 [C]
Key fingerprint = 5789 2205 8EED 7849 2058 4DFA 1A3F E8DD 02C0 515E
uid W. S. Wellington <my@email.com>
As of GPG version 2.1, a revocation certificate is automatically generated at this time.
Export the key ID as a variable (KEYID
) for use later:
$ export KEYID=0x1A3FE8DD02C0515E
Edit the Master key to add subkeys:
$ gpg --expert --edit-key $KEYID
Secret key is available.
sec rsa4096/0xEA5DE91459B80592
created: 2017-10-09 expires: never usage: C
trust: ultimate validity: ultimate
[ultimate] (1). W. S. Wellington <my@email.com>
Use 4096-bit keysize - or 2048-bit on NEO.
Use a 1 year expiration - it can always be renewed using the offline Master certification key.
Create a signing key by selecting (4) RSA (sign only)
:
gpg> addkey
Key is protected.
You need a passphrase to unlock the secret key for
user: "W. S. Wellington <my@email.com>"
4096-bit RSA key, ID 0x1A3FE8DD02C0515E, created 2016-05-24
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
Your selection? 4
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 1y
Key expires at Mon 10 Sep 2018 00:00:00 PM UTC
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
sec rsa4096/0x1A3FE8DD02C0515E
created: 2017-10-09 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0x4353637AC444F49B
created: 2017-10-09 expires: 2018-10-09 usage: S
[ultimate] (1). W. S. Wellington <my@email.com>
Next, create an encryption key by selecting (6) RSA (encrypt only)
:
gpg> addkey
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
Your selection? 6
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 1y
Key expires at Mon 10 Sep 2018 00:00:00 PM UTC
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
sec rsa4096/0x1A3FE8DD02C0515E
created: 2017-10-09 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0x4353637AC444F49B
created: 2017-10-09 expires: 2018-10-09 usage: S
ssb rsa4096/0xCDF4DD5522C8A286
created: 2017-10-09 expires: 2018-10-09 usage: E
[ultimate] (1). W. S. Wellington <my@email.com>
Finally, create an authentication key.
GPG doesn’t provide an authenticate-only key type, so select (8) RSA (set your own capabilities)
and toggle the required capabilities until the only allowed action is Authenticate
:
gpg> addkey
Please select what kind of key you want:
(3) DSA (sign only)
(4) RSA (sign only)
(5) Elgamal (encrypt only)
(6) RSA (encrypt only)
(7) DSA (set your own capabilities)
(8) RSA (set your own capabilities)
(10) ECC (sign only)
(11) ECC (set your own capabilities)
(12) ECC (encrypt only)
(13) Existing key
Your selection? 8
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Sign Encrypt
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? S
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Encrypt
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? E
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions:
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? A
Possible actions for a RSA key: Sign Encrypt Authenticate
Current allowed actions: Authenticate
(S) Toggle the sign capability
(E) Toggle the encrypt capability
(A) Toggle the authenticate capability
(Q) Finished
Your selection? Q
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
Requested keysize is 4096 bits
Please specify how long the key should be valid.
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0) 1y
Key expires at Mon 10 Sep 2018 00:00:00 PM UTC
Is this correct? (y/N) y
Really create? (y/N) y
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
sec rsa4096/0x1A3FE8DD02C0515E
created: 2017-10-09 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0x4353637AC444F49B
created: 2017-10-09 expires: 2018-10-09 usage: S
ssb rsa4096/0xCDF4DD5522C8A286
created: 2017-10-09 expires: 2018-10-09 usage: E
ssb rsa4096/0x4CBAA29AD396D84E
created: 2017-10-09 expires: 2018-10-09 usage: A
[ultimate] (1). W. S. Wellington <my@email.com>
gpg> save
List the generated secret keys and verify the output:
$ gpg --list-secret-keys
/tmp.FLZC0xcM/pubring.kbx
-------------------------------------------------------------------------
sec rsa4096/0x1A3FE8DD02C0515E 2017-10-09 [C]
Key fingerprint = 5789 2205 8EED 7849 2058 4DFA 1A3F E8DD 02C0 515E
uid W. S. Wellington <my@email.com>
ssb rsa4096/0x4353637AC444F49B 2017-10-09 [S] [expires: 2018-10-09]
ssb rsa4096/0xCDF4DD5522C8A286 2017-10-09 [E] [expires: 2018-10-09]
ssb rsa4096/0x4CBAA29AD396D84E 2017-10-09 [A] [expires: 2018-10-09]
Optional Add any additional identities or email addresses now using the adduid
command.
To verify with OpenPGP key checks, use the automated key best practice checker:
$ gpg --export $KEYID | hokey lint
The output will display any problems with your key in red text. If everything is green, your key passes each of the tests. If it is red, your key has failed one of the tests.
hokey may warn (orange text) about cross certification for the authentication key. GPG’s Signing Subkey Cross-Certification documentation has more detail on cross certification, and gpg v2.2.1 notes “subkey
does not sign and so does not need to be cross-certified". hokey may also indicate a problem (red text) with `Key expiration times: []` on the primary key (see [Note #3](#notes) about not setting an expiry for the primary key).
The Master and subkeys will be encrypted with your passphrase when exported.
Save a copy of your keys:
$ gpg --armor --export-secret-keys $KEYID > $GNUPGHOME/mastersub.key
$ gpg --armor --export-secret-subkeys $KEYID > $GNUPGHOME/sub.key
On Windows, note that using any extension other than .gpg
or attempting IO redirection to a file will garble the secret key, making it impossible to import it again at a later date:
$ gpg --armor --export-secret-keys $KEYID -o \path\to\dir\mastersub.gpg
$ gpg --armor --export-secret-subkeys $KEYID -o \path\to\dir\sub.gpg
Once GPG keys are moved to YubiKey, they cannot be extracted again!
Make sure you have made an encrypted backup before proceeding. An encrypted USB drive or container can be made using VeraCrypt.
Also consider using a paper copy of the keys as an additional backup measure.
Note YubiKey NEO shipped after November 2015 have all modes enabled; so this step may be skipped. Older versions of the YubiKey NEO may need to be reconfigured as a composite USB device (HID + CCID) which allows OTPs to be emitted while in use as a SmartCard.
Plug in YubiKey and configure it with the ykpersonalize
utility:
$ sudo ykpersonalize -m82
Firmware version 4.3.7 Touch level 527 Program sequence 1
The USB mode will be set to: 0x82
Commit? (y/n) [n]: y
The -m option is the mode command. To see the different modes, enter ykpersonalize -help
. Mode 82 (in hex) enables the YubiKey NEO as a composite USB device (HID + CCID). Once you have changed the mode, you need to re-boot the YubiKey, so remove and re-insert it. On YubiKey NEO with firmware version 3.3 or higher, you can enable composite USB device with -m86
instead of -m82
.
Windows Use the YubiKey NEO Manager to enable CCID functionality.
Use GPG to configure YubiKey as a smartcard:
$ gpg --card-edit
Reader ...........: Yubico Yubikey 4 OTP U2F CCID
Application ID ...: D2760001240102010006055532110000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 05553211
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]
The default PIN is 123456
and default Admin PIN (PUK) is 12345678
. CCID-mode PINs can be up to 127 ASCII characters long.
The Admin PIN is required for some card operations and to unblock a PIN that has been entered incorrectly more than three times. See the GnuPG documentation on Managing PINs for details.
gpg/card> admin
Admin commands are allowed
gpg/card> passwd
gpg: OpenPGP card no. D2760001240102010006055532110000 detected
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit
Your selection? 3
PIN changed.
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit
Your selection? 1
PIN changed.
1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit
Your selection? q
Some fields are optional.
gpg/card> name
Cardholder's surname: Duh
Cardholder's given name: Dr
gpg/card> lang
Language preferences: en
gpg/card> login
Login data (account name): my@email.com
gpg/card> [Press Enter]
Application ID ...: D2760001240102010006055532110000
Version ..........: 2.1
Manufacturer .....: unknown
Serial number ....: 05553211
Name of cardholder: W. S. Wellington
Language prefs ...: en
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: my@email.com
Private DO 4 .....: [not set]
Signature PIN ....: not forced
Key attributes ...: 2048R 2048R 2048R
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]
gpg/card> quit
Important Transferring keys to YubiKey using keytocard
is a destructive, one-way operation only. Make sure you’ve made a backup before proceeding: keytocard
converts the local, on-disk key into a stub, which means the on-disk copy is no longer usable to transfer to subsequent security key devices or mint additional keys.
Previous GPG versions required the toggle
command before selecting keys. The currently selected key(s) are indicated with an *
. When moving keys only one key should be selected at a time.
$ gpg --edit-key $KEYID
Secret key is available.
sec rsa4096/0x1A3FE8DD02C0515E
created: 2017-10-09 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0x4353637AC444F49B
created: 2017-10-09 expires: 2018-10-09 usage: S
ssb rsa4096/0xCDF4DD5522C8A286
created: 2017-10-09 expires: 2018-10-09 usage: E
ssb rsa4096/0x4CBAA29AD396D84E
created: 2017-10-09 expires: 2018-10-09 usage: A
[ultimate] (1). W. S. Wellington <my@email.com>
Select and move the signature key. You will be prompted for the key passphrase and Admin PIN.
gpg> key 1
sec rsa4096/0x1A3FE8DD02C0515E
created: 2017-10-09 expires: never usage: C
trust: ultimate validity: ultimate
ssb* rsa4096/0x4353637AC444F49B
created: 2017-10-09 expires: 2018-10-09 usage: S
ssb rsa4096/0xCDF4DD5522C8A286
created: 2017-10-09 expires: 2018-10-09 usage: E
ssb rsa4096/0x4CBAA29AD396D84E
created: 2017-10-09 expires: 2018-10-09 usage: A
[ultimate] (1). W. S. Wellington <my@email.com>
gpg> keytocard
Please select where to store the key:
(1) Signature key
(3) Authentication key
Your selection? 1
You need a passphrase to unlock the secret key for
user: "W. S. Wellington <my@email.com>"
4096-bit RSA key, ID 0x4353637AC444F49B, created 2016-05-24
Type key 1
again to de-select and key 2
to select the next key:
gpg> key 1
gpg> key 2
sec rsa4096/0x1A3FE8DD02C0515E
created: 2017-10-09 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0x4353637AC444F49B
created: 2017-10-09 expires: 2018-10-09 usage: S
ssb* rsa4096/0xCDF4DD5522C8A286
created: 2017-10-09 expires: 2018-10-09 usage: E
ssb rsa4096/0x4CBAA29AD396D84E
created: 2017-10-09 expires: 2018-10-09 usage: A
[ultimate] (1). W. S. Wellington <my@email.com>
gpg> keytocard
Please select where to store the key:
(2) Encryption key
Your selection? 2
[...]
Type key 2
again to deselect and key 3
to select the last key:
gpg> key 2
gpg> key 3
sec rsa4096/0x1A3FE8DD02C0515E
created: 2017-10-09 expires: never usage: C
trust: ultimate validity: ultimate
ssb rsa4096/0x4353637AC444F49B
created: 2017-10-09 expires: 2018-10-09 usage: S
ssb rsa4096/0xCDF4DD5522C8A286
created: 2017-10-09 expires: 2018-10-09 usage: E
ssb* rsa4096/0x4CBAA29AD396D84E
created: 2017-10-09 expires: 2018-10-09 usage: A
[ultimate] (1). W. S. Wellington <my@email.com>
gpg> keytocard
Please select where to store the key:
(3) Authentication key
Your selection? 3
gpg> save
Verify the subkeys have moved to YubiKey as indicated by ssb>
:
$ gpg --list-secret-keys
/tmp.FLZC0xcM/pubring.kbx
-------------------------------------------------------------------------
sec rsa4096/0x1A3FE8DD02C0515E 2017-10-09 [C]
Key fingerprint = 5789 2205 8EED 7849 2058 4DFA 1A3F E8DD 02C0 515E
uid W. S. Wellington <my@email.com>
ssb> rsa4096/0x4353637AC444F49B 2017-10-09 [S] [expires: 2018-10-09]
ssb> rsa4096/0xCDF4DD5522C8A286 2017-10-09 [E] [expires: 2018-10-09]
ssb> rsa4096/0x4CBAA29AD396D84E 2017-10-09 [A] [expires: 2018-10-09]
Mount another USB disk to copy the public key, or save it somewhere where it can be easily accessed later.
Important Without importing the public key, you will not be able to use GPG to encrypt, decrypt, nor sign messages. However, you will still be able to use YubiKey for SSH authentication.
$ gpg --armor --export $KEYID > /mnt/public-usb-key/pubkey.txt
Windows:
$ gpg --armor --export $KEYID -o \path\to\dir\pubkey.gpg
Optional Upload the public key to a public keyserver:
$ gpg --send-key $KEYID
$ gpg --keyserver pgp.mit.edu --send-key $KEYID
$ gpg --keyserver keys.gnupg.net --send-key $KEYID
After some time, the public key will to propagate to other servers.
Ensure you have:
Remove the secret keys from the GPG keyring:
$ gpg --delete-secret-key $KEYID
Important Make sure you have securely erased all generated keys and revocation certificates if a Live image was not used!
To import the public key from a file on an encrypted USB disk:
$ gpg --import /mnt/pubkey.txt
gpg: key 0x1A3FE8DD02C0515E: public key "W. S. Wellington <my@email.com>" imported
gpg: Total number processed: 1
gpg: imported: 1
To download the public key from a keyserver:
$ gpg --recv $KEYID
gpg: requesting key 0x1A3FE8DD02C0515E from hkps server hkps.pool.sks-keyservers.net
[...]
gpg: key 0x1A3FE8DD02C0515E: public key "W. S. Wellington <my@email.com>" imported
gpg: Total number processed: 1
gpg: imported: 1
Edit the Master key to assign it ultimate trust by selecting trust
then option 5
:
$ gpg --edit-key $KEYID
Secret key is available.
gpg> trust
pub 4096R/0x1A3FE8DD02C0515E created: 2016-05-24 expires: never usage: C
trust: unknown validity: unknown
sub 4096R/0x4353637AC444F49B created: 2017-10-09 expires: 2018-10-09 usage: S
sub 4096R/0xCDF4DD5522C8A286 created: 2017-10-09 expires: 2018-10-09 usage: E
sub 4096R/0x4CBAA29AD396D84E created: 2017-10-09 expires: 2018-10-09 usage: A
[ unknown] (1). W. S. Wellington <my@email.com>
Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)
1 = I don't know or won't say
2 = I do NOT trust
3 = I trust marginally
4 = I trust fully
5 = I trust ultimately
m = back to the main menu
Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y
pub 4096R/0x1A3FE8DD02C0515E created: 2016-05-24 expires: never usage: C
trust: ultimate validity: unknown
sub 4096R/0x4353637AC444F49B created: 2017-10-09 expires: 2018-10-09 usage: S
sub 4096R/0xCDF4DD5522C8A286 created: 2017-10-09 expires: 2018-10-09 usage: E
sub 4096R/0x4CBAA29AD396D84E created: 2017-10-09 expires: 2018-10-09 usage: A
[ unknown] (1). W. S. Wellington <my@email.com>
gpg> save
Re-connect YubiKey and check the status:
$ gpg --card-status
Application ID ...: D2760001240102010006055532110000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 05553211
Name of cardholder: W. S. Wellington
Language prefs ...: en
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: my@email.com
Signature PIN ....: not forced
Key attributes ...: 4096R 4096R 4096R
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 3 3
Signature counter : 0
Signature key ....: 48EA C77E 66CB B696 F2AB DE03 4353 637A C444 F49B
created ....: 2016-05-24 23:22:01
Encryption key....: 6FAF 26E6 6E3A A21F A1D1 E30C CDF4 DD55 22C8 A286
created ....: 2016-05-24 23:29:03
Authentication key: 82BE 7837 6A3F 2E7B E556 5E35 3F29 127E 7964 9A3D
created ....: 2016-05-24 23:36:40
General key info..: pub 4096R/0x4353637AC444F49B 2016-05-24 W. S. Wellington <my@email.com>
sec# 4096R/0x1A3FE8DD02C0515E created: 2016-05-24 expires: never
ssb> 4096R/0x4353637AC444F49B created: 2017-10-09 expires: 2018-10-09
card-no: 0006 05553211
ssb> 4096R/0xCDF4DD5522C8A286 created: 2017-10-09 expires: 2018-10-09
card-no: 0006 05553211
ssb> 4096R/0x4CBAA29AD396D84E created: 2017-10-09 expires: 2018-10-09
card-no: 0006 05553211
sec#
indicates master key is not available (as it should be stored encrypted offline).
Note If you see General key info..: [none]
in the output instead - go back and import the public key using the previous step.
Note This is not possible on YubiKey NEO.
By default, YubiKey will perform key operations without requiring a touch from the user. To require a touch for every authentication, use the YubiKey Manager and Admin PIN:
$ ykman openpgp touch aut on
To require a touch for signing and encryption operations:
$ ykman openpgp touch sig on
$ ykman openpgp touch enc on
The YubiKey will blink when it’s waiting for touch.
The following websites were instrumental in my understanding of this process.