## U2F for login and sudo access I followed this guide: https://support.yubico.com/hc/en-us/articles/360016649099-Ubuntu-Linux-Login-Guide-U2F For step 3, I only did the user-specific pamu2fcfg setup; I did not put it at the system level. This makes the `$HOME` partition portable, and allows different users on the system to require U2F and/or use different keys. > ## Challenge-Response auth with YubiKey > > When I originally purchased my key, and for four years thereafter, I used the challenge-response feature for restricting user authentication and sudo access. > I found with the update to Ubuntu 20.10, however, that challenge-respose no longer worked; even with a known, valid key, I could no longer login. > I'm retaining this information here for posterity, but will also note that there's a more up-to-date article covering this now maintained by Yubico: https://support.yubico.com/hc/en-us/articles/360016649079-Ubuntu-Linux-Login-Guide-Challenge-Response > > Started with https://developers.yubico.com/yubico-pam/Authentication_Using_Challenge-Response.html > > - Install yubikey-personalization > - Install libpam-yubico > - The instructions indicated that I'd get a question about the PAM > configuration line. I did not. As such, I had to run `dpkg-reconfigure > libpam-yubico` to do so. When I did, I used the value > `mode=challenge-response`. Additionally, this then gives the dialog > associated with `pam-auth-update`, and initially has `Yubico` selected. The > instructions are unclear at this point, and make it seem like you should > deselect everything; DO NOT DO THIS! Just deselect the Yubico entry. > - Set the appropriate yubikey mode: `sudo ykpersonalize -m86`. > - Mode 6 allows the yubikey 4 to act as each of OTP, U2F, and CCID. > - OTP allows it to be used as a one-time-password device with the yubicloud > as a replacement for things like google authenticator. > - U2F allows it to be used as a universal 2 factor auth device, which we > will be using with the challenge-response settings for PAM. > - CCID allows it to be used as a smartcard for usage with GPG. > - Mode 80 sets the `MODE_FLAG_EJECT` mode, which allows it to "eject" itself > and then "re-insert" itself when touched for an OTP. Combine it with the > above modes. > - Set slot 2 as a challenge-response slot: > `ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -oserial-api-visible` > (This is also required for usage as a GPG smartcard) > - Create the challenge/response for your user: > - `mkdir $HOME/.yubico` > - `ykpamcfg -2 -v` > - Note: if you have an encrypted home directory, you MUST do this differently! > In that case: > - `sudo mkdir /var/yubico` > - `sudo chmod +t /var/yubico` > - `sudo chmod 777 /var/yubico` > - `ykpamcfg -2 -v -p /var/yubico` > - Update the PAM configuration. > - Edit `/etc/pam.d/common-auth` > - Check for the line: `auth required pam_yubico.so mode=challenge-response`; > if not present, create it. > - IF YOU HAVE AN ENCRYPTED HOME DIRECTORY, add the verbiage > `chalresp_path=/var/yubico` to the end of the line. > - Open a root terminal in your shell: `sudo -s` (This is a fail-safe, to > ensure that if any configuration is wrong, you can disable the yubico PAM > requirements.) > - In a separate terminal, run `sudo pam-auth-update`, and enable the Yubico > module. > - Test it. `Ctrl-Alt-F1` to get to the TTY. > - Remove your yubikey > - Attempt to login. It should fail. > - Insert your yubikey. > - Attempt to login. It should succeed. > - exit. > - `Alt-F7` to get back to your GUI. In fact, at this point, your GUI should > likely be at the lock screen, and you should find that you'll be unable to > unlock it without the yubikey inserted! > > ## Adding Yubikey as a sudo authentication mechanism > > I followed this guide: https://defensiveinfosec.wordpress.com/2013/07/09/adding-otp-wyubikey-to-ubuntu-13-04-to-sudo-or-login/ ## PGP on Yubikey I tried three different approaches: - Upgrading my existing 1024bit DSA key to a 2048bit RSA key (see below) - https://www.esev.com/blog/post/2015-01-pgp-ssh-key-on-yubikey-neo/ - https://www.preining.info/blog/2016/04/gnupg-subkeys-yubikey/ None worked out-of-the-box. In the first case, I never successfully got the key updated. On further reading, I discovered (a) the instructions are out-of-date, and (b) using subkeys effectively solves the problem anyways. The latter two use that latter approach. With the latter two, I ran into issues with each. For the blog post from Eric Severance (www.esev.com), I ran into an issue only at the very end, when I'd do my `gpg --card-status`: there was no "general key info" listed, which meant I did not have a valid keychain. For the blog post from Norbert Preining (www.preining.info), I'd run into issues as soon as I issued `keytocard`, due to missing a secret key. What I discovered was this: the instructions from Norber Preining *did* work, if I generated the subkeys *using gpg2, and not gpg1*. Once I did that, everything fell into place. This means, of course, that I cannot use these for embedded systems, or when using GPG v1. I'm okay with that. ### Updating GIT Once you've got everything setup, it's time to tell Git to use your new signing key from your yubikey. If you run `gpg -K`, look for your signing key (it'll have `[S]` at the end of the key's listing, just prior to the expiration date). Grab the key ID, and now run: ```bash $ git config --global user.signingkey ``` Also, since *I must use gpg2*, I had to update one other configuration, to tell git to use gpg2 when signing commits: ```bash $ git config --global gpg.program gpg2 ``` ### Using touch for authentication Instead of entering a GPG passphrase and/or the PIN associated with the yubikey, I wanted to be able to just *touch* the key instead. Why? - Simpler. I have enough passwords running through my head, and I don't want to have to remember them all. - More secure. The yubikey acts as an input device by default, which means that, technically, a keylogger could potentially sniff it. On top of that, a keylogger could sniff the PIN associated with it. While I may still need to enter the PIN for the first signing or encryption operation I performed, I can reduce the number of opportunities. I followed the [directions on the yubico site for enabling touch operations](https://developers.yubico.com/PGP/Card_edit.html). It worked flawlessly immediately; I ran it using: ```bash $ yubitouch.sh sig on $ yubitouch.sh aut on $ yubitouch.sh dec on ``` I've put the script in `$HOME/bin/yubitouch.sh`, and kept it around. ### Updating the private (master) key and/or subkeys You may need to update the private (master) key and/or its subkeys from time to time: - to reset expiration - to update the user identity This turned out to be somewhate complicated, and, again, no one source I read worked for me, though this one [by Abel Luck and forked from Kenny MacDermid](https://gist.github.com/abeluck/3383449) came quite close. Essentially, you do the following: - Pull the data from your USB into a new folder locally, setting the folder permissions to 0700. Export a variable, GPGHOME, pointing to this directory. - `killall gpg-agent` (just to be on the safe side) - Edit the key, using `gpg --homedir $GPGHOME --edit-key ` - Make whatever changes you need. For example, to reset expiry: - Type `key ` to select a key. - Type `expire` and follow the prompts. - Type `key ` to deselect the key. - Repeat the previous steps for each expired key. - Type `save` to save the changes. - Export the secret key: `gpg --homedir $GPGHOME -a --export-secret-keys > $GPGHOME/master-secret-key.gpg` - Export the secret keys for the subkeys: `gpg --homedir $GPGHOME -a --export-secret-subkeys > $GPGHOME/sub-secret-keys.gpg` - Export the public key: `gpg --homedir $GPGHOME -a --export > $GPGHOME/pub-key.gpg` If you follow along with the above link, you'll notice I'm not exporting the key *stubs*. I don't do this, because *it did not work for me*. When I would import them, they'd be imported as keys *missing their secrets*, but not as keys *on a device*. At this point, you have one of two options: - Import the public key into a new, empty `$HOME/.gnupg/` directory - Import the public key into the existing `$HOME/.gnupg/` directory I chose the first. To do this, I also had to first save my keyring, which can be in `$HOME/.gnupg/pubring.gpg`, but, starting in GPG 2.1, is in `$HOME/.gnupg/pubring.kbx`; I'll import that later. - `killall gpg-agent` (just to be on the safe side) - `mv $HOME/.gnupg $HOME/.gnupg.$(date +%Y%m%d)` - `mkdir -p $HOME/.gnupg` - `chmod 700 $HOME/.gnupg` - `gpg --import $GPGHOME/pub-key.gpg` - `gpg --import $GPGHOME/master-secret-key.gpg` - `gpg --import $GPGHOME/sub-secret-keys.gpg` - Import the keyring: - If you have a non-zero byte `pubring.gpg`: `gpg --import $HOME/.gnupg.$(date +%Y%m%d)/pubring.gpg` - For `pubring.kbx`: `gpg --keyring=$HOME/.gnupg.$(date +%Y%m%d)/pubring.kbx --export | gpg --import` At this point, we also need to mark the root key as trusted. Run `gpg --edit-key `, type `trust`, and mark the key as "ultimately trusted". You should also do this for any UIDs present: `uid ` + `trust`, and mark as "ultimately trusted". Check to see if the yubikey has the keys properly marked, using `gpg --card-status`. You should see each of your keys with a "card-no: ..." entry; validate that the expiry is correct. If not, or if card-status doesn't show any keys, you will need to move the keys onto the yubikey again. - Kill any running gpg-agents (`killall gpg-agent`) - Run `gpg --edit-key ` - `toggle` - Select the first subkey to move - `keytocard`; select the appopriate key type, agree to overwrite, and go from there. - Deselect the key, and select the next one; wash, rinse, repeat. - `save` At this point, if you do `gpg --list-secret-keys`, you should see it correctly. Finally: whenever you re-add keys to the card, *you have to re-enable touch capabilities*. ~~Run the `$HOME/bin/yubitouch.sh` script to do this, running it once for each of the key types (sig, aut, dec).~~ Remove your card, and re-insert it; run `dmesg` to ensure you see it, and then run `ykman openpgp info` to verify that the `ykman` tool can see it. Then run `ykman openpgp keys set-touch dec on` and `ykman openpgp keys set-touch sig on` (which enables touch for de/encryption and signature, but keeps it off for authentication; this allows you to enter your admin PIN once per SSH agent session, instead of requiring a touch each time you connect). ### GitHub and signing keys So, now it's time to update GitHub. I had already associated my GPG key with the service, but found that new releases I signed with my *signing key* were not showing up as verified. This bothered me. So, I tried to export the signing key and upload it as an additional key on github. That failed; github complained that the key was already present. Deleting the existing key indicated that I'd lose all verification on other releases I'd made. In the end, I bit the bullet, and: - Deleted my existing key - Uploaded the contents of my pub-key.pgp Lo and behold, all my previous verified releases were still verified, and new releases were as well! Additionally, the GPG key listing showed all my subkeys, and all email addresses associated with the primary key. ### Using gpg-agent as an ssh-agent I did the following: - First, remove `ssh-agent` from any oh-my-zsh plugin lists you're using. - Second, `echo "enable-ssh-support" >> $HOME/.gnupg/gpg-agent.conf` - Third, add a `$HOME/.zsh/gpg-ssh-agent.zsh` script with the following contents: ```bash #!/usr/bin/zsh gpg-connect-agent /bye export SSH_AUTH_SOCK=$HOME/.gnupg/S.gpg-agent.ssh ``` and, when done, `source` it in your `.zshrc`. Open a new terminal, `killall ssh-agent`, and run `ssh-add -l -E md5`; you should see your GPG authentication key now listed as a key. You can add your default SSH keys as well, using `ssh-add`; they'll be added to `$HOME/.gnupg/sshcontrol`; I chose not to, and instead used the results of `gpg --export-ssh-key ` to seed `authorized_keys` entries everywhere. The one issue I ran into was on AWS. I found I needed to ssh ANYWHERE else first, and, once I had, SSH to AWS worked fine. ### Convert DSA 1024 GPG key to RSA 2048 I never got this to work; these are just my notes on what I tried. Followed instructions at: http://atom.smasher.org/gpg/gpg-migrate.txt First thing to remember: make sure you're using GPG v1 releases, and not v2, as it manipulates the secring.gpg and pubring.gpg. (I tried originally after first aliasing gpg to gpg2, which led me down an incorrect path.) My second try didn't work, either; in the end, I had the new key, but the original key was not attached as a subkey properly. Trying a third time... All goes well until I get to the step where the author notes "this last part makes no sense to me (but it doesn't seem to work otherwise)". When I get to this step, after removing the new key from the keyring, the *original* key disappears as well. Importing the exported secret and key imports the new key, but the *original* key is no longer listed as a subkey at that point; it's just completely gone. I tried creating and verifying signatures *before* that step, and this worked for the *new* key, but not the *original*; at that point, the original is not considered a valid secret signing key. One thing to note: when I listed the keys under the new key, the original, as a subkey, does not have any modes associated with it. I wonder if I need to toggle the capabilities somehow first? > ## Encrypted Disk Yubikey Challenge > > > I enabled disk encryption on two of my laptops, from 2017-2019. > > However, I found this was quite a bit of effort, and highly risky in the case where you have no backup key. > > I keep the instructions for posterity only. > > I have enabled disk encryption on two of my laptops. On Linux, the encryption > system is called luks, and there's a tool that will essentially allow you to > use the yubikey as the primary authentication mechanism. > > I followed the instructions in the blog post https://www.howtoforge.com/ubuntu-two-factor-authentication-with-yubikey-for-harddisk-encryption-with-luks > The first key difference, is that you no longer need a PPA in order to > install the yubikey-luks package; on 17.10, at least, it's "just there". > The second difference is that it does _not_ assume that `/dev/sda5` is the > encrypted partition, but instead `/dev/sda3`. You do not need to set any > environment variables, however; the `yubikey-luks-enroll` script now also accepts > a `-d` (for "device partition") argument, allowing you to specify it during > invocation: > > ```bash > $ sudo yubikey-luks-enroll -d /dev/sda5 > ```