Skip to content

Instantly share code, notes, and snippets.

@BrendanLeber
Forked from ageis/YubiKey-GPG-SSH-guide.md
Created June 29, 2018 19:07
Show Gist options
  • Select an option

  • Save BrendanLeber/6e1e662717ef019575a2d897ca9075dd to your computer and use it in GitHub Desktop.

Select an option

Save BrendanLeber/6e1e662717ef019575a2d897ca9075dd to your computer and use it in GitHub Desktop.

Revisions

  1. @ageis ageis revised this gist Mar 4, 2018. 1 changed file with 0 additions and 2 deletions.
    2 changes: 0 additions & 2 deletions YubiKey-GPG-SSH-guide.md
    Original file line number Diff line number Diff line change
    @@ -6,8 +6,6 @@
    <tr>
    <td>

    <sub>This is an update of an [earlier guide](https://gist.github.com/ageis/5b095b50b9ae6b0aa9bf) which had become dated, having been originally written with the [OpenPGP card from g10 code](https://g10code.com/p-card.html) (in combination with a [Gemalto shell token v2](http://www.smartcardfocus.us/shop/ilp/id~461/gemalto-gempc-shell-token-v2-idbridge-k30-/p/index.shtml)) in mind, which is now relatively ancient. Some options and comments were meant for older versions of GPG (2.0.x and before) and a user environment consisting of a previous version of [Tails OS](https://tails.boum.org/) based upon Debian wheezy. The previous version also advocated what's known as a "dual-smartcard" setup, which is less common, more expensive and trickier to work with, making it less feasible for most people. I've already updated what I can and verified the entire process, but let me know if you encounter problems.</sub>

    You'll probably be working with a single smartcard, so you'll want only one primary key (`1. Sign & Certify`) and two associated subkeys (`2. Encrypt, 3. Authenticate`).

    By skipping straight to the "Load subkeys onto the smartcard" section one could feasibly transfer an already-existent, unexpired GPG key(s) to your new YubiKey... If you wish to attempt that just make sure you back up the secret keys first. Depending on your threat model and interest in seriously protecting the secrets, and your level of confidence in the theoretical impenetrability of your own machine, I suppose you have the option to ignore the Tails and air-gap stuff and do all of this on your regular work computer—but be aware this directly compromises security and kind of defeats the whole point of moving such keys to separate offline hardware.
  2. @ageis ageis revised this gist Mar 2, 2018. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions YubiKey-GPG-SSH-guide.md
    Original file line number Diff line number Diff line change
    @@ -133,6 +133,8 @@ Why are there two? One is for decrypting messages and making signatures, which h

    Preferably right away you should initialize your new smartcard, setting some of the variables if you so choose (stuff like `name`, `url`, `login`, `lang`, `sex`), but most importantly modify the default PIN and admin PIN. You can do this by running `gpg --card-edit` and typing `admin` and then `help` to list available commands. Use `passwd` to change your PINs. You can also toggle the `forcesig` flag to control whether you'd like to require a PIN to be entered every time you sign a message.

    Remember to set up a Reset Code! The pinentry dialog looks nearly the same as that which prompts for a password to an SSH key and accepts non-numeric input... By default if you get this wrong 10 times, you'll have to factory reset and start over, but setting a reset code in advance will mean you'll be able to unlock your card.

    </td>
    </tr>
    </tbody>
  3. @ageis ageis revised this gist Feb 28, 2018. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions YubiKey-GPG-SSH-guide.md
    Original file line number Diff line number Diff line change
    @@ -328,7 +328,7 @@ To make sure your smartcard works in every terminal you open, it helps to add th
    GPG_TTY=$(tty)
    export GPG_TTY
    if [ -z "$GPG_AGENT_INFO" ]; then
    eval $(gpg-agent --daemon --options ~/.gnupg/gpg-agent.conf)
    eval "$(gpg-agent --daemon --options ~/.gnupg/gpg-agent.conf)"
    fi
    ```

    @@ -443,7 +443,7 @@ Finally, the relevant addition to ~/.profile:

    ```
    if [ -z "$DIRMNGR_INFO" ]; then
    eval $(dirmngr --daemon)
    eval "$(dirmngr --daemon)"
    fi
    ```

  4. @ageis ageis revised this gist Feb 28, 2018. 1 changed file with 6 additions and 5 deletions.
    11 changes: 6 additions & 5 deletions YubiKey-GPG-SSH-guide.md
    Original file line number Diff line number Diff line change
    @@ -328,15 +328,16 @@ To make sure your smartcard works in every terminal you open, it helps to add th
    GPG_TTY=$(tty)
    export GPG_TTY
    if [ -z "$GPG_AGENT_INFO" ]; then
    eval `gpg-agent --daemon --options ~/.gnupg/gpg-agent.conf``
    eval $(gpg-agent --daemon --options ~/.gnupg/gpg-agent.conf)
    fi
    ```

    If you intend to use gpg-agent as your SSH agent and authenticate to servers that way then include these lines as well:

    ```
    if [ -z "$SSH_AUTH_SOCK" ]; then
    export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
    SSH_AUTH_SOCK="$(gpgconf --list-dirs agent-ssh-socket)"
    export SSH_AUTH_SOCK
    fi
    ```

    @@ -367,15 +368,15 @@ On GnuPG 2.0.x, when you run gpg-agent with `enable-ssh-support` so that it may

    1. Ensure `enable-ssh-support` is present in `~/.gnupg/gpg-agent.conf`.

    2. Fetch the keygrip of your master public key via `gpg2 --with-keygrip -k` and add these 40 hex digits as a line to`~/.gnupg/sshcontrol` if they're absent.
    2. Fetch the keygrip of your master public key via `gpg2 --with-keygrip -K` and add these 40 hex digits as a line to`~/.gnupg/sshcontrol` if they're absent.

    3. Make sure something similar to `gpg-agent --daemon --options ~/.gnupg/gpg-agent.conf` is running in the background via `ps -u`. If you then run `ssh-add -l` it should list an SSH identity corresponding to the RSA key on your smartcard.

    4. Check `echo $SSH_AUTH_SOCK` - it should be pointing to gpg-agent's socket instead of ssh-agent. If it's not you have to kill ssh-agent with fire or make sure it doesn't start.

    5. Get the 16-bit long ID of your Authenticate subkey and feed it into `gpgkey2ssh`:

    `gpgkey2ssh 00698E823F6DD692 > ssh_id.pub`
    `gpg --export-ssh-key 00698E823F6DD692 > ssh_id.pub`

    You can add the contents of ssh_id.pub to `~/.ssh/authorized_keys` on any system you like, or you can try `ssh-copy-id`.

    @@ -442,7 +443,7 @@ Finally, the relevant addition to ~/.profile:

    ```
    if [ -z "$DIRMNGR_INFO" ]; then
    eval `dirmngr --daemon
    eval $(dirmngr --daemon)
    fi
    ```

  5. @ageis ageis revised this gist Feb 4, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion YubiKey-GPG-SSH-guide.md
    Original file line number Diff line number Diff line change
    @@ -90,7 +90,7 @@ Least commonly used, this is used for authenticating your identity via a challen
    </tbody>
    </table>

    I recommend generating keys on a secure computer instead of on the card, because it allows more flexibility. Ideally this means a machine running [Tails](https://tails.boum.org/) or one that is air-gapped and not connected to the internet. Refer to the [Tails documentation](https://tails.boum.org/doc/first_steps/index.en.html) for instruction on creating a bootable USB with encrypted persistent storage if you'd like to go that route.
    I recommend generating keys on a secure computer instead of on the card, because it allows more flexibility. Ideally this means a machine running [Tails](https://tails.boum.org/) or [Qubes OS](https://www.qubes-os.org), more generally one that is air-gapped and not connected to the internet. Refer to the [Tails documentation](https://tails.boum.org/doc/first_steps/index.en.html) for instruction on creating a bootable USB with encrypted persistent storage if you'd like to go that route.

    It's also good to possess offline backups, since with on-card generation you're basically screwed when/if you physically lose your YubiKey. The supposed backup option for smartcard key generation is actually pretty weak and useless. In theory private keys can never leave the device once they're loaded.

  6. @ageis ageis revised this gist Dec 20, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions YubiKey-GPG-SSH-guide.md
    Original file line number Diff line number Diff line change
    @@ -432,9 +432,9 @@ keyserver hkps://hkps.pool.sks-keyservers.net
    hkp-cacert ~/.gnupg/sks-keyservers.netCA.pem
    ```

    Supposedly there's a great option called `use-tor` (which would conceal your location and IP address while requesting a key), but there's a bug and I haven't been able to get it working. I will update this as soon as I do.
    There's a great option called `use-tor`, which would conceal your location and IP address while requesting a key, if you have a Tor daemon running and available. In my torrc I enable the SOCKSPort with no authentication for localhost and set CookieAuthentication to 1. You may also need to fiddle with the ControlPort or torsocks.conf.

    Run `touch ~/.gnupg/dirmngr_ldapservers.conf`. Without a blank file present thre, you'll receive a needless warning message.
    Run `touch ~/.gnupg/dirmngr_ldapservers.conf`. Without a blank file present there, you'll receive a needless warning message.

    Download the certificate here: [https://sks-keyservers.net/sks-keyservers.netCA.pem](https://sks-keyservers.net/sks-keyservers.netCA.pem) ([more info](https://sks-keyservers.net/verify_tls.php))

  7. @ageis ageis revised this gist Nov 27, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion YubiKey-GPG-SSH-guide.md
    Original file line number Diff line number Diff line change
    @@ -47,7 +47,7 @@ A basic grasp of the concept of capabilities of private keys is helpful, so here
    <td>

    With this you may sign other keys, "certifying" them, indicating you verified their identity and trust that person.
    Usually being the on primary/master key as well, this is required to add or revoke UIDs, alter key details, etc.
    Ordinarily set on the primary/master key, this is required to add or revoke UIDs, alter key details, etc.

    </td>
    </tr>
  8. @ageis ageis revised this gist Aug 26, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions YubiKey-GPG-SSH-guide.md
    Original file line number Diff line number Diff line change
    @@ -428,7 +428,7 @@ log-file ~/.gnupg/dirmngr.log`
    debug-level basic
    verbose
    disable-ipv6
    keyserver [hkps://hkps.pool.sks-keyservers.net](hkps://hkps.pool.sks-keyservers.net)
    keyserver hkps://hkps.pool.sks-keyservers.net
    hkp-cacert ~/.gnupg/sks-keyservers.netCA.pem
    ```

    @@ -448,7 +448,7 @@ fi

    ### Maximally secure gpg.conf, algorithm, digest and cipher preferences

    It's crucial to prefer 32-bit long key IDs instead of short ones, which are vulnerable to malicious collision. See [Evil 32](https://evil32.com/) for details. It's also not necessary to reveal your GnuPG version, better to retrieve keys via HKPS rather than unencrypted HKP, as well as insisting upon the strongest cipher and digest algorithms available.
    It's crucial to prefer 32-bit long key IDs instead of short ones, which are vulnerable to malicious collision. See [Evil 32](https://evil32.com/) for details. It's also not necessary to reveal your GnuPG version, better to retrieve keys via HKPS rather than plain/unencrypted HKP, as well as insisting upon the strongest cipher and digest algorithms available.

    Here's what my ~/.gnupg/gpg.conf looks like:

  9. @ageis ageis created this gist Aug 26, 2017.
    502 changes: 502 additions & 0 deletions YubiKey-GPG-SSH-guide.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,502 @@
    # YubiKey 4 series GPG and SSH setup guide
    #### Written for fairly adept technical users, preferably of Debian GNU/Linux, not for absolute beginners.

    <table>
    <tbody>
    <tr>
    <td>

    <sub>This is an update of an [earlier guide](https://gist.github.com/ageis/5b095b50b9ae6b0aa9bf) which had become dated, having been originally written with the [OpenPGP card from g10 code](https://g10code.com/p-card.html) (in combination with a [Gemalto shell token v2](http://www.smartcardfocus.us/shop/ilp/id~461/gemalto-gempc-shell-token-v2-idbridge-k30-/p/index.shtml)) in mind, which is now relatively ancient. Some options and comments were meant for older versions of GPG (2.0.x and before) and a user environment consisting of a previous version of [Tails OS](https://tails.boum.org/) based upon Debian wheezy. The previous version also advocated what's known as a "dual-smartcard" setup, which is less common, more expensive and trickier to work with, making it less feasible for most people. I've already updated what I can and verified the entire process, but let me know if you encounter problems.</sub>

    You'll probably be working with a single smartcard, so you'll want only one primary key (`1. Sign & Certify`) and two associated subkeys (`2. Encrypt, 3. Authenticate`).

    By skipping straight to the "Load subkeys onto the smartcard" section one could feasibly transfer an already-existent, unexpired GPG key(s) to your new YubiKey... If you wish to attempt that just make sure you back up the secret keys first. Depending on your threat model and interest in seriously protecting the secrets, and your level of confidence in the theoretical impenetrability of your own machine, I suppose you have the option to ignore the Tails and air-gap stuff and do all of this on your regular work computer—but be aware this directly compromises security and kind of defeats the whole point of moving such keys to separate offline hardware.

    The purpose of having a YubiKey should be clear: even if your computer gets completely owned, then your keys and any encrypted data are still safe. They offer other useful functions as well, like static password output (which is well-suited for PAM user login or mounting LUKS password-protected volumes) or HOTP, or [Universal Two-Factor](https://www.yubico.com/solutions/fido-u2f/) (U2F) a [FIDO Alliance](https://fidoalliance.org/) standard used by Google, Facebook, GitHub, Dropbox and more... But here I'm just covering GPG and SSH. To customize and configure the configuration slots, download & use [NEO manager](https://developers.yubico.com/yubikey-neo-manager/) and/or the [Personalization Tool](https://developers.yubico.com/yubikey-personalization/).

    The YubiKey 4 has a status light. You can tell when it's actively performing RSA operations and the like. In certain modes, your computer simply recognizes it as a classic US keyboard. The button has three ways to activate the two individual configuration slots to accomplish different things: a single press, double tap, and a long press. You'll quickly learn to avoid pressing it by accident when there's an important password encoded in there :stuck_out_tongue_winking_eye:

    * **[More official documentation](https://www.yubico.com/support/knowledge-base/categories/guides/)**
    * **[The YubiKey Manual](https://www.yubico.com/wp-content/uploads/2015/03/YubiKeyManual_v3.4.pdf)**
    * **[OpenPGP card functional specification](https://www.g10code.com/docs/openpgp-card-3.0.pdf)**
    * **[OpenPGP Message Format](https://tools.ietf.org/html/rfc4880)**
    * **[Another YubiKey setup guide of high quality](https://github.com/drduh/YubiKey-Guide)**
    * **[Some OSX-specific setup info](https://github.com/liyanchang/yubikey-setup)**

    </td>
    </tr>
    </tbody>
    </table>

    An OpenPGP smartcard always has three separate key slots. These are labeled Signature, Encryption and Authentication. Each subkey usually has its own key ID.

    There are a few different approaches to getting started with a smartcard. Sometimes people leverage two smartcards and put their master key away at home on one, and use a second with the subkeys for signing and decryption for daily usage... Additionally, people may migrate previously generated keys to a new card. We won't be doing any of that.

    In this guide, you will generate a master key with the Certify and Sign capabilities and two subkeys with each of the Encrypt and Authenticate capabilities respectively and move them to one YubiKey.

    A basic grasp of the concept of capabilities of private keys is helpful, so here's a table for elucidation:

    <table>
    <tbody>
    <tr>
    <td>

    <b>Certify</b>

    </td>
    <td>

    With this you may sign other keys, "certifying" them, indicating you verified their identity and trust that person.
    Usually being the on primary/master key as well, this is required to add or revoke UIDs, alter key details, etc.

    </td>
    </tr>
    <tr>
    <td>

    <b>Encrypt</b>

    </td>
    <td>

    Pretty self-explanatory... A key possessing this capability can decrypt messages to it.

    </td>
    </tr>
    <tr>
    <td>

    <b>Sign</b>

    </td>
    <td>

    A key possessing this capability may create digital signatures of messages, showing incontrovertible proof that you wrote the message or possess the key. Often confused with certify because this capability doesn't sign other keys.

    </td>
    </tr>
    <tr>
    <td>

    <b>Authenticate</b>

    </td>
    <td>

    Least commonly used, this is used for authenticating your identity via a challenge-response protocol. Hence can be used as an SSH identity.

    </td>
    </tr>
    </tbody>
    </table>

    I recommend generating keys on a secure computer instead of on the card, because it allows more flexibility. Ideally this means a machine running [Tails](https://tails.boum.org/) or one that is air-gapped and not connected to the internet. Refer to the [Tails documentation](https://tails.boum.org/doc/first_steps/index.en.html) for instruction on creating a bootable USB with encrypted persistent storage if you'd like to go that route.

    It's also good to possess offline backups, since with on-card generation you're basically screwed when/if you physically lose your YubiKey. The supposed backup option for smartcard key generation is actually pretty weak and useless. In theory private keys can never leave the device once they're loaded.

    By default, GPG generates a master key with the Certify and Sign capabilities and a subkey with the Encrypt capability. We will override this using expert mode.

    First, make sure you're running GnuPG 2.x. This is important because you _can't_ use 4096-bit RSA keys on most smartcards with GnuPG 1.x. If it's not already the default, then a Bash alias will suffice, e.g. `alias gpg=gpg2`.

    If you use the [Enigmail](https://www.enigmail.net/index.php/en/) add-on for [Thunderbird](https://www.mozilla.org/en-US/thunderbird/) mail client, the GPG path should be set to /usr/bin/gpg2.

    If you plan to use a YubiKey on Linux in general, you'll need to add udev rules in order to interact with the device. Create a file named `70-yubikey.rules` in `/etc/udev/rules.d` with the following contents:

    <table>
    <tbody>
    <tr>
    <th>

    <pre>
    ACTION=="add|change", SUBSYSTEM=="usb", ATTR{idVendor}=="1050", ATTR{idProduct}=="0010|0110|0111|0114|0116|0401|0403|0405|0407|0410", OWNER="amnesia", TAG+="uaccess"
    </pre>

    </th>
    </tr>
    </tbody>
    </table>

    :warning: Replace the `OWNER` attribute above with the name of your system's user that you ordinarily login as before saving. That's only a Tails convention.

    Then run: `sudo udevadm control --reload-rules`. Now you may insert or re-plug the USB device and you should have normal user access, which may be confirmed with `gpg --card-status`

    <table>
    <tbody>
    <tr>
    <td>

    **The default PIN: 123456**

    **The default admin PIN: 12345678**

    Why are there two? One is for decrypting messages and making signatures, which happens frequently. The admin PIN is needed to modify certain card attributes, which is more rare once you're set up. Write down and memorize your PIN choices, since the card is programmed to become blocked after the maximum number of incorrect attempts (usually 10).

    Preferably right away you should initialize your new smartcard, setting some of the variables if you so choose (stuff like `name`, `url`, `login`, `lang`, `sex`), but most importantly modify the default PIN and admin PIN. You can do this by running `gpg --card-edit` and typing `admin` and then `help` to list available commands. Use `passwd` to change your PINs. You can also toggle the `forcesig` flag to control whether you'd like to require a PIN to be entered every time you sign a message.

    </td>
    </tr>
    </tbody>
    </table>

    :information_source: For the sake of brevity, this guide assumes that you will always enter correct passphrases and PINs, and answer Yes by typing `y` when prompted. Now let's get started!

    ### Generate the master key

    `gpg --expert --full-gen-key`

    Select 8: RSA (set your own capabilities)

    Select E to toggle off the Encrypt capability, which will leave you with only Sign + Certify.

    Set a 4096 bit key size.

    Set the expiration date.

    Setup a UID.

    Setup a passphrase.

    The primary key is generated. Note your new key ID, as you'll be needing it henceforth.

    ### Add UIDs

    `gpg --expert --edit-key <longid>`

    Use `gpg> adduid` to add as many UIDs or e-mail addresses as you need. Once you're done, toggle to `gpg> uid <#>` and use the `gpg> primary` command to set the primary UID.

    Now we will generate subkeys for each additional capability to be transferred to the main smartcard designated for daily use.

    ### Create the Encrypt key

    `gpg> addkey`

    Select 6: RSA (encrypt only).

    Set a 4096 bit key size.

    Set the expiration date.

    The first subkey is generated.

    ### Create the Authenticate key

    `gpg> addkey`

    Select 8: RSA (set your own capabilities)

    Select S and E to toggle off the Sign and Encrypt capabilities.

    Select A to toggle on the Authenticate capability and press Q.

    Set a 4096 bit key size.

    Set the expiration date.

    The second subkey is generated.

    ### Set trust level

    By the way, you should probably set the public key to the ultimate trust level.

    `gpg> trust`

    Select 5 = I trust ultimately.

    `gpg> save`

    Save the key(s) you've been creating.

    ### Add signatures

    If you want to sign your new master key with a previous key that you're transitioning from, then the time is now. How else will people know you're not an impostor?

    gpg -u <your_old_keyid> --sign-key <longid>

    ### Generate revocation certificate

    It's a good idea to create a revocation certificate, in case the YubiKey is lost or your private key is somehow compromised.

    gpg --output revoke.asc --gen-revoke <longid>

    ### Backup everything

    gpg --armor --output privkey.sec --export-secret-key <longid>
    gpg --armor --output subkeys.sec --export-secret-subkeys <longid>
    gpg --armor --output pubkey.asc --export <longid>

    You can move these private keys plus the revocation certificate someplace safe, like an encrypted partition or offline storage media.

    As mentioned earlier, you can use `gpg --card-edit` to setup your smartcard: set the PINs, and variables like language, sex, your first and last name, or a public URL for downloading your key.

    So, after you've created keys, initialized the card and set new PINs, let's import the keys.

    ### Loading keys onto the smartcard

    `gpg --expert --edit-key <longid>`

    `gpg> toggle`

    `gpg> keytocard`

    Answer 'y' to "Really move the primary key?"

    Select 1: Signature key.

    Enter your passphrase and admin PIN as required.

    `gpg> key 1`

    `gpg> keytocard`

    Select 2: Encryption key

    Enter your passphrase and admin PIN as required.

    Un-toggle key one: `gpg> key 1`

    Toggle key two: `gpg> key 2`

    `gpg> keytocard`

    Select 3: Authentication key.

    Enter your passphrase and admin PIN as required.

    Un-toggle key two: `gpg> key 2`

    `gpg> save`

    - - -

    Your card is good and ready to go. :thumbsup: Now what?

    You shouldn't have to delete any secret keys, as they were moved to the smartcard. When you use either `keytocard` command or perform key generation _on_ the card, GnuPG places a "stub" in your keyring so that it knows the actual secret key material is located on the smartcard. It appears as though you possess the secret key in your keyring but you actually don't, and you can't decrypt anything without the card. It's just a stub pointing to the smartcard — which is something you do want to keep if you'd like this to be usable.

    So what if you deleted the secret keys anyway and lost the stubs? Just run `gpg --card-status` anywhere or open the 'Manage Smartcard' menu in Enigmail in order to instantly re-associate and populate your keyring with the information from your smartcard. However, always keep in mind that you need the corresponding public key in your keyring to work with the smartcard on whatever computer you're using.

    After you purposely delete the secret key stubs from your keyring (otherwise it will say the keys are already associated with another card), you can even put these same keys on a _different_ smartcard by repeating part of the process above.

    However, you should probably backup or transfer these stubs to your regular computer first, (in the double-smartcard setup I mentioned, when the stubs point to separate smartcards for different subkeys, it's very difficult to re-create if you lose them)—but [it can be done](https://lists.gnupg.org/pipermail/gnupg-users/2013-September/047412.html) using a tool called gpgsplit. Without all of the correct stubs in your keyring, GnuPG won't prompt you to insert your other smartcard with a different serial number when you try to certify another key or alter attributes.

    gpg --armor --output stubs.asc --export-secret-keys <longid>

    Transfer this file to your regular, non-airgapped machine and run `gpg --import stubs.asc`. This doesn't contain any actual secret key material — that's been migrated to the smartcard(s). Also make sure you transfer and import a copy of your `pubkey.asc` for things to work properly.

    :smiley: You now have a working OpenPGP smartcard for use with GPG, [Enigmail](https://www.enigmail.net/) and more! Now you can let people know about your new key, upload it to keyservers, publish a transition statement, and all of that fun stuff.

    There are lots of keychain apps (Seahorse, GNU Privacy Assistant, and more), however I don't really recommend any of them. Also the kbxutil tool provided to convert GnuPG (1.x/2.0) keyrings to the new, keybox format in GnuPG 2.1 which has been advertised as faster, I've found to be unusable.

    ## Two-factor authentication

    If you want, your YubiKey could be required to login to your computer or unlock your screen or access your session keyring and such things.

    This can be done using the highly extensible [Yubico PAM module](https://developers.yubico.com/yubico-pam/). If you're interested, then `apt-get install libpam-yubico` then refer to the relevant documentation or manual from Yubico:

    * [Two Factor PAM Configuration](https://developers.yubico.com/yubico-pam/Two_Factor_PAM_Configuration.html)
    * [Local Authentication Using Challenge Response](https://developers.yubico.com/yubico-pam/Authentication_Using_Challenge-Response.html)
    * [Setting up your YubiKey for challenge response authentication on Max OS X](https://developers.yubico.com/yubico-pam/MacOS_X_Challenge-Response.html)

    If you're not already aware, similar functionality may be achieved by Google's [libpam-google-authenticator](https://github.com/google/google-authenticator-libpam).

    ## Tips

    Fortunately Enigmail now has an option to [conceal PGP metadata](https://www.ietf.org/proceedings/92/slides/slides-92-appsawg-0.pdf), moving the Subject field into the encrypted message body. Just get into the [preferences](https://enigmail.wiki/Advanced_Operations) and set `extensions.enigmail.protectHeaders` to true. Never write a descriptive or accurate subject line, this actively works against the reason you're encrypting messages in the first place. Think of some nonsense instead.

    Addressing that same problem, GPG senders have options `--throw-keyids` or `--hidden-recipient` which make it so that any eavesdropper or recipient cannot tell which key or person the message is intended for. However, this is very annoying for those on the other end, as it means recipients have to try ALL of their local secret keys attempting to decrypt the message until finding the right one (or not). So I don't recommend it; it's merely good to be aware of.

    Always use PGP/MIME if you can, it's superior to in-line PGP with better support for rich text or HTML, etc.

    If you block your card or lose your PIN, all is not lost. There's a `factory-reset` command, or you could just pipe [this text file](https://gist.github.com/ageis/84e61bf7b595807dd4c08743f78792e7/raw/d29166984bd6f5016f86a982b26a1ccdb5ca14ba/smartcard-reset.txt) containing raw hex commands to the device: `gpg-connect-agent < smartcard-reset.txt`.

    ## Troubleshooting

    In a GNOME desktop environment, gnome-keyring-daemon (at least at the time of first authorship) once had a bad habit of hijacking the GnuPG agent, causing cards and readers to be unrecognized or to behave unpredictably. Many of these issues go away if you disable the SSH & GPG components of gnome-keyring-daemon and let gpg-agent handle them instead. Run gnome-keyring-daemon with only `--components=pkcs11,secrets`.

    To do this you can `rm /etc/xdg/autostart/gnome-keyring-ssh.desktop` and `gnome-keyring-gpg.desktop` or just add `Hidden=true` plus `X-GNOME-Autostart-enabled=false` to those launchers. If you prefer, you can create a new launcher only for starting gpg-agent (ideally in `~/.config/autostart`).

    If you are experiencing "Card not available" or "Card error", then you might want to try killing and restarting gpg-agent.

    :warning: The udev rules are absolutely essential! If they don't work when you plug the device in, then as a workaround you can always run `lsusb` to figure out the device and bus ID and then manually `chown` the YubiKey device file to your user in `/dev/bus/usb/<bus#>/<device#>`

    It can sometimes be a bit challenging to get your smartcard working reliably until you figure these things out.

    ## Related configuration

    To make sure your smartcard works in every terminal you open, it helps to add the following to `~/.profile`:

    ```
    GPG_TTY=$(tty)
    export GPG_TTY
    if [ -z "$GPG_AGENT_INFO" ]; then
    eval `gpg-agent --daemon --options ~/.gnupg/gpg-agent.conf``
    fi
    ```

    If you intend to use gpg-agent as your SSH agent and authenticate to servers that way then include these lines as well:

    ```
    if [ -z "$SSH_AUTH_SOCK" ]; then
    export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
    fi
    ```

    While we're at it, here's what my `~/.gnupg/gpg-agent.conf` looks like lately:

    ```
    pinentry-program /usr/bin/pinentry-qt4
    enable-ssh-support
    keep-display
    keep-tty
    default-cache-ttl 3600
    max-cache-ttl 7200
    scdaemon-program /usr/lib/gnupg/scdaemon
    sh
    debug-level basic
    homedir ~/.gnupg
    ```

    :information_source: This particular configuration depends on two packages you must install via apt-get, `pinentry-qt4` and `scdaemon`. If you're annoyed by debug messages then just set that value to `none`.

    Back in the day most pinentry programs didn't allow pasting from clipboard, making them hard to use with a password manager. For this ability one once had to build from source with `./configure --enable-pinentry-qt4-clipboard=yes.` This isn't the case anymore in Debian stretch/9.x!

    ## Using the smartcard key for SSH authentication

    It's all just RSA, right? OpenPGP, OpenSSL, and OpenSSH keys can work together and be friends. To be specific, you can use your 4096-bit Authenticate key on the smartcard with SSH. This has the advantage that you can't log in to any servers without possession of the device. It's easiest to do with the latest GnuPG 2.1.x, otherwise you may have to `apt-get install monkeysphere` and use the `openpgp2ssh` tool, which we're going to skip. **Note:** this won't work at all unless you've already set a non-default smartcard PIN of at least 6 digits.

    On GnuPG 2.0.x, when you run gpg-agent with `enable-ssh-support` so that it may take over for ssh-agent, your smartcard's Authenticate subkey should automatically be recognized as a valid SSH key and become available for the SSH client to use as an identity. But you might have trouble seeing it or getting it to work, so here are some extra steps which can assist the process:

    1. Ensure `enable-ssh-support` is present in `~/.gnupg/gpg-agent.conf`.

    2. Fetch the keygrip of your master public key via `gpg2 --with-keygrip -k` and add these 40 hex digits as a line to`~/.gnupg/sshcontrol` if they're absent.

    3. Make sure something similar to `gpg-agent --daemon --options ~/.gnupg/gpg-agent.conf` is running in the background via `ps -u`. If you then run `ssh-add -l` it should list an SSH identity corresponding to the RSA key on your smartcard.

    4. Check `echo $SSH_AUTH_SOCK` - it should be pointing to gpg-agent's socket instead of ssh-agent. If it's not you have to kill ssh-agent with fire or make sure it doesn't start.

    5. Get the 16-bit long ID of your Authenticate subkey and feed it into `gpgkey2ssh`:

    `gpgkey2ssh 00698E823F6DD692 > ssh_id.pub`

    You can add the contents of ssh_id.pub to `~/.ssh/authorized_keys` on any system you like, or you can try `ssh-copy-id`.

    Now your SSH agent should be communicating with gpg-agent and the RSA Authenticate key on your smartcard is a valid SSH identity. When you run SSH with your smartcard connected, it will automatically attempt to authenticate using it.

    - - -

    If you run into trouble getting your YubiKey to work with SSH, there is a method of last resort, but it's quite technically involved:

    1. GnuPG 2.0 or later doesn't allow exporting private keys which aren't protected with a password. This is the main problem.

    2. So, somehow downgrade to GnuPG v1.4.x or [build it from source](https://gnupg.org/download/index.html) and import the keys into your secring.gpg (not the secring.kbx) and use `gpg --expert --edit-key [primary_keyid_here]`, remove the passphrase entirely, and then save the key.

    :information_source: Setting an alternate `$GNUPGHOME` or `--homedir` when working between different GnuPG versions may be more efficient. Another tip, if you're on 2.1 with Debian stretch by default, then just `make` instead of `make install` while building 2.0.x or 1.4.x, and move binaries from `./g10` in the source tree to `/usr/local/bin` with names like 'gpgv14' or 'gpgv20'.

    3. Find the key ID for your Authenticate subkey, it'll of course be different from the Encrypt and Sign subkeys (see `gpg --card-status`)

    4. Export only the subkey if possible, with minimal options: `gpg --export-options export-reset-subkey-passwd,export-minimal,no-export-attributes --export-secret-subkeys ![authenticate_subkey_id_here] > subkey.sec`

    5. Note the prefixing of an exclamation point to the beginning of the key ID – this lets you target specific subkeys for export.

    6. If you still have no luck, then do a complete `--export-secret-keys` of the primary key to a file like `key.sec`, run `gpg --list-packets key.sec` to examine your key(s) and their capabilities. I recommend installing a program called pgpdump which can also come in handy for analyzing keys, messages and signatures.

    7. You then must run `gpgsplit key.sec` in an empty folder which will disassemble your key into its constituent packets and write them to the current working directory.

    8. Then, concatenate the secret subkey and its signature packet together, ignoring all other keys and packets. The main point is to get rid of the master/primary key, since the protection/passphrase requirements are problematic here. Ultimately isolating your SSH RSA Authenticate key might look something like this: `cat 000005-002.sig 000004-007.secret_subkey > ssh_key.sec`

    9. Finally the isolated `ssh_key.sec` file is something that can be fed via STDIN to openpgp2ssh (another tool provided by monkeysphere). Like in the example above, just do `openpgp2ssh [authenticate_subkey_id_here] > ssh_key.sec`

    10. If step 9 fails then return to step 6 and try with `--export-secret-subkeys [primary_keyid_here] subkey.sec` instead.

    ### More resources:

    * [https://www.inuits.eu/blog/ssh-authentication-your-pgp-key](https://www.inuits.eu/blog/ssh-authentication-your-pgp-key)

    * [http://www.bootc.net/archives/2013/06/09/my-perfect-gnupg-ssh-agent-setup/](http://www.bootc.net/archives/2013/06/09/my-perfect-gnupg-ssh-agent-setup/)

    * [https://gist.github.com/andrewlkho/7373190](https://gist.github.com/andrewlkho/7373190)

    * [https://spin.atomicobject.com/2014/02/09/gnupg-openpgp-smartcard/](https://spin.atomicobject.com/2014/02/09/gnupg-openpgp-smartcard/)

    ### Transport layer security in fetching from keyservers

    A requirement of accessing HKPS keyservers, especially through apt-key operations, is to install gnupg-curl.

    Here's the contents of my ~/.gnupg/dirmngr.conf:

    ```
    log-file ~/.gnupg/dirmngr.log`
    debug-level basic
    verbose
    disable-ipv6
    keyserver [hkps://hkps.pool.sks-keyservers.net](hkps://hkps.pool.sks-keyservers.net)
    hkp-cacert ~/.gnupg/sks-keyservers.netCA.pem
    ```

    Supposedly there's a great option called `use-tor` (which would conceal your location and IP address while requesting a key), but there's a bug and I haven't been able to get it working. I will update this as soon as I do.

    Run `touch ~/.gnupg/dirmngr_ldapservers.conf`. Without a blank file present thre, you'll receive a needless warning message.

    Download the certificate here: [https://sks-keyservers.net/sks-keyservers.netCA.pem](https://sks-keyservers.net/sks-keyservers.netCA.pem) ([more info](https://sks-keyservers.net/verify_tls.php))

    Finally, the relevant addition to ~/.profile:

    ```
    if [ -z "$DIRMNGR_INFO" ]; then
    eval `dirmngr --daemon
    fi
    ```

    ### Maximally secure gpg.conf, algorithm, digest and cipher preferences

    It's crucial to prefer 32-bit long key IDs instead of short ones, which are vulnerable to malicious collision. See [Evil 32](https://evil32.com/) for details. It's also not necessary to reveal your GnuPG version, better to retrieve keys via HKPS rather than unencrypted HKP, as well as insisting upon the strongest cipher and digest algorithms available.

    Here's what my ~/.gnupg/gpg.conf looks like:

    ```
    keyserver hkps://hkps.pool.sks-keyservers.net
    keyserver-options ca-cert-file=~/.gnupg/sks-keyservers.netCA.pem
    use-agent
    charset utf8
    keyid-format 0xlong
    no-emit-version
    #default-key 0x00000000 REPLACE THIS!!
    no-greeting
    cipher-algo AES256
    digest-algo SHA256
    personal-digest-preferences SHA512
    personal-cipher-preferences AES256 AES
    cert-digest-algo SHA512
    default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB ZIP Uncompressed
    s2k-cipher-algo AES256
    s2k-digest-algo SHA512
    s2k-mode 3
    s2k-count 65536
    keyserver-options no-honor-keyserver-url
    utf8-strings
    auto-key-locate keyserver cert pka
    ```

    ### More resources:

    * Riseup.net's OpenPGP best practices: [https://riseup.net/en/security/message-security/openpgp/best-practices](https://riseup.net/en/security/message-security/openpgp/best-practices)

    * [https://spin.atomicobject.com/2013/11/24/secure-gpg-keys-guide/](https://spin.atomicobject.com/2013/11/24/secure-gpg-keys-guide/)

    * [https://alexcabal.com/creating-the-perfect-gpg-keypair/](https://alexcabal.com/creating-the-perfect-gpg-keypair/)

    * [https://davesteele.github.io/gpg/2014/09/20/anatomy-of-a-gpg-key/](https://davesteele.github.io/gpg/2014/09/20/anatomy-of-a-gpg-key/)

    * [https://incenp.org/notes/2015/gnupg-for-ssh-authentication.html](https://incenp.org/notes/2015/gnupg-for-ssh-authentication.html)

    ### For the nerds:

    * [Learn about the flags and fields that appear in key packets plus what they mean](https://git.gnupg.org/cgi-bin/gitweb.cgi?p=gnupg.git;a=blob_plain;f=doc/DETAILS)
    * [Awesomely simplified and easily comprehensible version of the OpenPGP specification](https://github.com/singpolyma/openpgp-spec)

    #### How to obtain the OpenPGP smartcards and USB readers

    I now recommend the [YubiKey series 4](https://www.yubico.com/2015/11/4th-gen-yubikey-4/) instead of the [OpenPGP smartcard from g10 code](http://shop.kernelconcepts.de/#openpgp). It's modern hardware, much faster, and has many great features. These devices can be [purchased from Amazon](http://www.amazon.com/Yubico-Y-158-YubiKey-4/dp/B018Y1Q71M/) or directly via [Yubico's website](https://www.yubico.com/product/yubikey-4-series/).

    It's also available in USB-C which works on your Android smartphone with [OpenKeychain](https://play.google.com/store/apps/details?id=org.sufficientlysecure.keychain&hl=en) or [Android Privacy Guard](https://play.google.com/store/apps/details?id=org.thialfihar.android.apg&hl=en) (APG) and integrates with [K-9 Mail](https://play.google.com/store/apps/details?id=com.fsck.k9&hl=en).

    _If you have questions or suggestions concerning any of the information within this guide, feel free to [contact me directly](https://cointel.pro)._