matthew revised this gist . Go to revision
No changes
matthew revised this gist . Go to revision
1 file changed, 323 insertions
yubikey-all-the-things.md(file created)
@@ -0,0 +1,323 @@ | |||
1 | + | ## U2F for login and sudo access | |
2 | + | ||
3 | + | I followed this guide: https://support.yubico.com/hc/en-us/articles/360016649099-Ubuntu-Linux-Login-Guide-U2F | |
4 | + | ||
5 | + | For step 3, I only did the user-specific pamu2fcfg setup; I did not put it at the system level. | |
6 | + | This makes the `$HOME` partition portable, and allows different users on the system to require U2F and/or use different keys. | |
7 | + | ||
8 | + | > ## Challenge-Response auth with YubiKey | |
9 | + | > | |
10 | + | > When I originally purchased my key, and for four years thereafter, I used the challenge-response feature for restricting user authentication and sudo access. | |
11 | + | > 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. | |
12 | + | > 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 | |
13 | + | > | |
14 | + | > Started with https://developers.yubico.com/yubico-pam/Authentication_Using_Challenge-Response.html | |
15 | + | > | |
16 | + | > - Install yubikey-personalization | |
17 | + | > - Install libpam-yubico | |
18 | + | > - The instructions indicated that I'd get a question about the PAM | |
19 | + | > configuration line. I did not. As such, I had to run `dpkg-reconfigure | |
20 | + | > libpam-yubico` to do so. When I did, I used the value | |
21 | + | > `mode=challenge-response`. Additionally, this then gives the dialog | |
22 | + | > associated with `pam-auth-update`, and initially has `Yubico` selected. The | |
23 | + | > instructions are unclear at this point, and make it seem like you should | |
24 | + | > deselect everything; DO NOT DO THIS! Just deselect the Yubico entry. | |
25 | + | > - Set the appropriate yubikey mode: `sudo ykpersonalize -m86`. | |
26 | + | > - Mode 6 allows the yubikey 4 to act as each of OTP, U2F, and CCID. | |
27 | + | > - OTP allows it to be used as a one-time-password device with the yubicloud | |
28 | + | > as a replacement for things like google authenticator. | |
29 | + | > - U2F allows it to be used as a universal 2 factor auth device, which we | |
30 | + | > will be using with the challenge-response settings for PAM. | |
31 | + | > - CCID allows it to be used as a smartcard for usage with GPG. | |
32 | + | > - Mode 80 sets the `MODE_FLAG_EJECT` mode, which allows it to "eject" itself | |
33 | + | > and then "re-insert" itself when touched for an OTP. Combine it with the | |
34 | + | > above modes. | |
35 | + | > - Set slot 2 as a challenge-response slot: | |
36 | + | > `ykpersonalize -2 -ochal-resp -ochal-hmac -ohmac-lt64 -oserial-api-visible` | |
37 | + | > (This is also required for usage as a GPG smartcard) | |
38 | + | > - Create the challenge/response for your user: | |
39 | + | > - `mkdir $HOME/.yubico` | |
40 | + | > - `ykpamcfg -2 -v` | |
41 | + | > - Note: if you have an encrypted home directory, you MUST do this differently! | |
42 | + | > In that case: | |
43 | + | > - `sudo mkdir /var/yubico` | |
44 | + | > - `sudo chmod +t /var/yubico` | |
45 | + | > - `sudo chmod 777 /var/yubico` | |
46 | + | > - `ykpamcfg -2 -v -p /var/yubico` | |
47 | + | > - Update the PAM configuration. | |
48 | + | > - Edit `/etc/pam.d/common-auth` | |
49 | + | > - Check for the line: `auth required pam_yubico.so mode=challenge-response`; | |
50 | + | > if not present, create it. | |
51 | + | > - IF YOU HAVE AN ENCRYPTED HOME DIRECTORY, add the verbiage | |
52 | + | > `chalresp_path=/var/yubico` to the end of the line. | |
53 | + | > - Open a root terminal in your shell: `sudo -s` (This is a fail-safe, to | |
54 | + | > ensure that if any configuration is wrong, you can disable the yubico PAM | |
55 | + | > requirements.) | |
56 | + | > - In a separate terminal, run `sudo pam-auth-update`, and enable the Yubico | |
57 | + | > module. | |
58 | + | > - Test it. `Ctrl-Alt-F1` to get to the TTY. | |
59 | + | > - Remove your yubikey | |
60 | + | > - Attempt to login. It should fail. | |
61 | + | > - Insert your yubikey. | |
62 | + | > - Attempt to login. It should succeed. | |
63 | + | > - exit. | |
64 | + | > - `Alt-F7` to get back to your GUI. In fact, at this point, your GUI should | |
65 | + | > likely be at the lock screen, and you should find that you'll be unable to | |
66 | + | > unlock it without the yubikey inserted! | |
67 | + | > | |
68 | + | > ## Adding Yubikey as a sudo authentication mechanism | |
69 | + | > | |
70 | + | > I followed this guide: https://defensiveinfosec.wordpress.com/2013/07/09/adding-otp-wyubikey-to-ubuntu-13-04-to-sudo-or-login/ | |
71 | + | ||
72 | + | ## PGP on Yubikey | |
73 | + | ||
74 | + | I tried three different approaches: | |
75 | + | ||
76 | + | - Upgrading my existing 1024bit DSA key to a 2048bit RSA key (see below) | |
77 | + | - https://www.esev.com/blog/post/2015-01-pgp-ssh-key-on-yubikey-neo/ | |
78 | + | - https://www.preining.info/blog/2016/04/gnupg-subkeys-yubikey/ | |
79 | + | ||
80 | + | None worked out-of-the-box. | |
81 | + | ||
82 | + | In the first case, I never successfully got the key updated. On further reading, | |
83 | + | I discovered (a) the instructions are out-of-date, and (b) using subkeys | |
84 | + | effectively solves the problem anyways. The latter two use that latter approach. | |
85 | + | ||
86 | + | With the latter two, I ran into issues with each. | |
87 | + | ||
88 | + | For the blog post from Eric Severance (www.esev.com), I ran into an issue only | |
89 | + | at the very end, when I'd do my `gpg --card-status`: there was no "general key | |
90 | + | info" listed, which meant I did not have a valid keychain. | |
91 | + | ||
92 | + | For the blog post from Norbert Preining (www.preining.info), I'd run into issues | |
93 | + | as soon as I issued `keytocard`, due to missing a secret key. | |
94 | + | ||
95 | + | What I discovered was this: the instructions from Norber Preining *did* work, if | |
96 | + | I generated the subkeys *using gpg2, and not gpg1*. Once I did that, everything | |
97 | + | fell into place. | |
98 | + | ||
99 | + | This means, of course, that I cannot use these for embedded systems, or when | |
100 | + | using GPG v1. I'm okay with that. | |
101 | + | ||
102 | + | ### Updating GIT | |
103 | + | ||
104 | + | Once you've got everything setup, it's time to tell Git to use your new signing | |
105 | + | key from your yubikey. | |
106 | + | ||
107 | + | If you run `gpg -K`, look for your signing key (it'll have `[S]` at the end of | |
108 | + | the key's listing, just prior to the expiration date). Grab the key ID, and now | |
109 | + | run: | |
110 | + | ||
111 | + | ```bash | |
112 | + | $ git config --global user.signingkey <key id> | |
113 | + | ``` | |
114 | + | ||
115 | + | Also, since *I must use gpg2*, I had to update one other configuration, to tell | |
116 | + | git to use gpg2 when signing commits: | |
117 | + | ||
118 | + | ```bash | |
119 | + | $ git config --global gpg.program gpg2 | |
120 | + | ``` | |
121 | + | ||
122 | + | ### Using touch for authentication | |
123 | + | ||
124 | + | Instead of entering a GPG passphrase and/or the PIN associated with the yubikey, | |
125 | + | I wanted to be able to just *touch* the key instead. Why? | |
126 | + | ||
127 | + | - Simpler. I have enough passwords running through my head, and I don't want to | |
128 | + | have to remember them all. | |
129 | + | - More secure. The yubikey acts as an input device by default, which means that, | |
130 | + | technically, a keylogger could potentially sniff it. On top of that, a | |
131 | + | keylogger could sniff the PIN associated with it. While I may still need to | |
132 | + | enter the PIN for the first signing or encryption operation I performed, I can | |
133 | + | reduce the number of opportunities. | |
134 | + | ||
135 | + | I followed the [directions on the yubico site for enabling touch | |
136 | + | operations](https://developers.yubico.com/PGP/Card_edit.html). It worked | |
137 | + | flawlessly immediately; I ran it using: | |
138 | + | ||
139 | + | ```bash | |
140 | + | $ yubitouch.sh sig on | |
141 | + | $ yubitouch.sh aut on | |
142 | + | $ yubitouch.sh dec on | |
143 | + | ``` | |
144 | + | ||
145 | + | I've put the script in `$HOME/bin/yubitouch.sh`, and kept it around. | |
146 | + | ||
147 | + | ### Updating the private (master) key and/or subkeys | |
148 | + | ||
149 | + | You may need to update the private (master) key and/or its subkeys from time to | |
150 | + | time: | |
151 | + | ||
152 | + | - to reset expiration | |
153 | + | - to update the user identity | |
154 | + | ||
155 | + | This turned out to be somewhate complicated, and, again, no one source I read | |
156 | + | worked for me, though this one [by Abel Luck and forked from Kenny | |
157 | + | MacDermid](https://gist.github.com/abeluck/3383449) came quite close. | |
158 | + | ||
159 | + | Essentially, you do the following: | |
160 | + | ||
161 | + | - Pull the data from your USB into a new folder locally, setting the folder | |
162 | + | permissions to 0700. Export a variable, GPGHOME, pointing to this directory. | |
163 | + | - `killall gpg-agent` (just to be on the safe side) | |
164 | + | - Edit the key, using `gpg --homedir $GPGHOME --edit-key <key>` | |
165 | + | - Make whatever changes you need. For example, to reset expiry: | |
166 | + | - Type `key <index>` to select a key. | |
167 | + | - Type `expire` and follow the prompts. | |
168 | + | - Type `key <index>` to deselect the key. | |
169 | + | - Repeat the previous steps for each expired key. | |
170 | + | - Type `save` to save the changes. | |
171 | + | - Export the secret key: `gpg --homedir $GPGHOME -a --export-secret-keys > $GPGHOME/master-secret-key.gpg` | |
172 | + | - Export the secret keys for the subkeys: `gpg --homedir $GPGHOME -a --export-secret-subkeys > $GPGHOME/sub-secret-keys.gpg` | |
173 | + | - Export the public key: `gpg --homedir $GPGHOME -a --export <key> > $GPGHOME/pub-key.gpg` | |
174 | + | ||
175 | + | If you follow along with the above link, you'll notice I'm not exporting the key | |
176 | + | *stubs*. I don't do this, because *it did not work for me*. When I would import | |
177 | + | them, they'd be imported as keys *missing their secrets*, but not as keys | |
178 | + | *on a device*. | |
179 | + | ||
180 | + | At this point, you have one of two options: | |
181 | + | ||
182 | + | - Import the public key into a new, empty `$HOME/.gnupg/` directory | |
183 | + | - Import the public key into the existing `$HOME/.gnupg/` directory | |
184 | + | ||
185 | + | I chose the first. To do this, I also had to first save my keyring, which can | |
186 | + | be in `$HOME/.gnupg/pubring.gpg`, but, starting in GPG 2.1, is in | |
187 | + | `$HOME/.gnupg/pubring.kbx`; I'll import that later. | |
188 | + | ||
189 | + | - `killall gpg-agent` (just to be on the safe side) | |
190 | + | - `mv $HOME/.gnupg $HOME/.gnupg.$(date +%Y%m%d)` | |
191 | + | - `mkdir -p $HOME/.gnupg` | |
192 | + | - `chmod 700 $HOME/.gnupg` | |
193 | + | - `gpg --import $GPGHOME/pub-key.gpg` | |
194 | + | - `gpg --import $GPGHOME/master-secret-key.gpg` | |
195 | + | - `gpg --import $GPGHOME/sub-secret-keys.gpg` | |
196 | + | - Import the keyring: | |
197 | + | - If you have a non-zero byte `pubring.gpg`: `gpg --import $HOME/.gnupg.$(date +%Y%m%d)/pubring.gpg` | |
198 | + | - For `pubring.kbx`: `gpg --keyring=$HOME/.gnupg.$(date +%Y%m%d)/pubring.kbx --export | gpg --import` | |
199 | + | ||
200 | + | At this point, we also need to mark the root key as trusted. Run | |
201 | + | `gpg --edit-key <key>`, type `trust`, and mark the key as "ultimately trusted". | |
202 | + | You should also do this for any UIDs present: `uid <num>` + `trust`, and mark as | |
203 | + | "ultimately trusted". | |
204 | + | ||
205 | + | Check to see if the yubikey has the keys properly marked, using `gpg --card-status`. | |
206 | + | You should see each of your keys with a "card-no: ..." entry; validate that the expiry is correct. | |
207 | + | ||
208 | + | If not, or if card-status doesn't show any keys, you will need to move the keys onto the yubikey again. | |
209 | + | ||
210 | + | - Kill any running gpg-agents (`killall gpg-agent`) | |
211 | + | - Run `gpg --edit-key <key>` | |
212 | + | - `toggle` | |
213 | + | - Select the first subkey to move | |
214 | + | - `keytocard`; select the appopriate key type, agree to overwrite, and go from | |
215 | + | there. | |
216 | + | - Deselect the key, and select the next one; wash, rinse, repeat. | |
217 | + | - `save` | |
218 | + | ||
219 | + | At this point, if you do `gpg --list-secret-keys`, you should see it correctly. | |
220 | + | ||
221 | + | Finally: whenever you re-add keys to the card, *you have to re-enable touch | |
222 | + | capabilities*. ~~Run the `$HOME/bin/yubitouch.sh` script to do this, running it | |
223 | + | once for each of the key types (sig, aut, dec).~~ Remove your card, and re-insert it; | |
224 | + | run `dmesg` to ensure you see it, and then run `ykman openpgp info` to verify that | |
225 | + | the `ykman` tool can see it. Then run `ykman openpgp keys set-touch dec on` and `ykman openpgp keys set-touch sig on` | |
226 | + | (which enables touch for de/encryption and signature, but keeps it off for authentication; | |
227 | + | this allows you to enter your admin PIN once per SSH agent session, instead of requiring | |
228 | + | a touch each time you connect). | |
229 | + | ||
230 | + | ### GitHub and signing keys | |
231 | + | ||
232 | + | So, now it's time to update GitHub. I had already associated my GPG key with the | |
233 | + | service, but found that new releases I signed with my *signing key* were not | |
234 | + | showing up as verified. This bothered me. | |
235 | + | ||
236 | + | So, I tried to export the signing key and upload it as an additional key on | |
237 | + | github. That failed; github complained that the key was already present. | |
238 | + | ||
239 | + | Deleting the existing key indicated that I'd lose all verification on other | |
240 | + | releases I'd made. | |
241 | + | ||
242 | + | In the end, I bit the bullet, and: | |
243 | + | ||
244 | + | - Deleted my existing key | |
245 | + | - Uploaded the contents of my pub-key.pgp | |
246 | + | ||
247 | + | Lo and behold, all my previous verified releases were still verified, and new | |
248 | + | releases were as well! Additionally, the GPG key listing showed all my subkeys, | |
249 | + | and all email addresses associated with the primary key. | |
250 | + | ||
251 | + | ### Using gpg-agent as an ssh-agent | |
252 | + | ||
253 | + | I did the following: | |
254 | + | ||
255 | + | - First, remove `ssh-agent` from any oh-my-zsh plugin lists you're using. | |
256 | + | - Second, `echo "enable-ssh-support" >> $HOME/.gnupg/gpg-agent.conf` | |
257 | + | - Third, add a `$HOME/.zsh/gpg-ssh-agent.zsh` script with the following contents: | |
258 | + | ```bash | |
259 | + | #!/usr/bin/zsh | |
260 | + | gpg-connect-agent /bye | |
261 | + | export SSH_AUTH_SOCK=$HOME/.gnupg/S.gpg-agent.ssh | |
262 | + | ``` | |
263 | + | and, when done, `source` it in your `.zshrc`. | |
264 | + | ||
265 | + | Open a new terminal, `killall ssh-agent`, and run `ssh-add -l -E md5`; you | |
266 | + | should see your GPG authentication key now listed as a key. You can add your | |
267 | + | default SSH keys as well, using `ssh-add`; they'll be added to | |
268 | + | `$HOME/.gnupg/sshcontrol`; I chose not to, and instead used the results of `gpg | |
269 | + | --export-ssh-key <key>` to seed `authorized_keys` entries everywhere. | |
270 | + | ||
271 | + | The one issue I ran into was on AWS. I found I needed to ssh ANYWHERE else | |
272 | + | first, and, once I had, SSH to AWS worked fine. | |
273 | + | ||
274 | + | ### Convert DSA 1024 GPG key to RSA 2048 | |
275 | + | ||
276 | + | I never got this to work; these are just my notes on what I tried. | |
277 | + | ||
278 | + | Followed instructions at: http://atom.smasher.org/gpg/gpg-migrate.txt | |
279 | + | ||
280 | + | First thing to remember: make sure you're using GPG v1 releases, and not v2, as | |
281 | + | it manipulates the secring.gpg and pubring.gpg. (I tried originally after first | |
282 | + | aliasing gpg to gpg2, which led me down an incorrect path.) | |
283 | + | ||
284 | + | My second try didn't work, either; in the end, I had the new key, but the | |
285 | + | original key was not attached as a subkey properly. | |
286 | + | ||
287 | + | Trying a third time... All goes well until I get to the step where the author | |
288 | + | notes "this last part makes no sense to me (but it doesn't seem to work | |
289 | + | otherwise)". When I get to this step, after removing the new key from the | |
290 | + | keyring, the *original* key disappears as well. Importing the exported secret | |
291 | + | and key imports the new key, but the *original* key is no longer listed as a | |
292 | + | subkey at that point; it's just completely gone. | |
293 | + | ||
294 | + | I tried creating and verifying signatures *before* that step, and this worked | |
295 | + | for the *new* key, but not the *original*; at that point, the original is not | |
296 | + | considered a valid secret signing key. | |
297 | + | ||
298 | + | One thing to note: when I listed the keys under the new key, the original, as a | |
299 | + | subkey, does not have any modes associated with it. I wonder if I need to toggle | |
300 | + | the capabilities somehow first? | |
301 | + | ||
302 | + | > ## Encrypted Disk Yubikey Challenge | |
303 | + | > | |
304 | + | > > I enabled disk encryption on two of my laptops, from 2017-2019. | |
305 | + | > > However, I found this was quite a bit of effort, and highly risky in the case where you have no backup key. | |
306 | + | > > I keep the instructions for posterity only. | |
307 | + | > | |
308 | + | > I have enabled disk encryption on two of my laptops. On Linux, the encryption | |
309 | + | > system is called luks, and there's a tool that will essentially allow you to | |
310 | + | > use the yubikey as the primary authentication mechanism. | |
311 | + | > | |
312 | + | > I followed the instructions in the blog post https://www.howtoforge.com/ubuntu-two-factor-authentication-with-yubikey-for-harddisk-encryption-with-luks | |
313 | + | > The first key difference, is that you no longer need a PPA in order to | |
314 | + | > install the yubikey-luks package; on 17.10, at least, it's "just there". | |
315 | + | > The second difference is that it does _not_ assume that `/dev/sda5` is the | |
316 | + | > encrypted partition, but instead `/dev/sda3`. You do not need to set any | |
317 | + | > environment variables, however; the `yubikey-luks-enroll` script now also accepts | |
318 | + | > a `-d` (for "device partition") argument, allowing you to specify it during | |
319 | + | > invocation: | |
320 | + | > | |
321 | + | > ```bash | |
322 | + | > $ sudo yubikey-luks-enroll -d /dev/sda5 | |
323 | + | > ``` |
Newer
Older