Yubikey 开箱上手

January 11, 2022 · 10 min read

建议 Tips

您正在查看印刷版本的博客, 印刷版本的博客可能会缺少部分交互功能, 部分内容显示不全或过时. 如果您在查看该印刷版博客时遇到了任何问题, 欢迎来此链接查看在线版: https://www.kxxt.dev/blog/yubikey-oobe/

You are viewing a printed version of this blog. It may lack some interactive features and some content might now be fully displayed or outdated. If you encounter any problems while viewing this printed version of the blog, feel free to view the online version here: https://www.kxxt.dev/blog/yubikey-oobe/

新买的 YubiKey 5 NFC 刚刚送到,趁此机会来水一篇博客(主要是跟着 https://github.com/drduh/YubiKey-Guide 这篇教程走)

首先在 Linux 系统上进行设置

在 Linux 上设置

我使用的是 Manjaro 操作系统,不同的 Linux 发行版安装依赖时所使用的命令可能会有所不同。

配置 GPG


sudo pacman -S hopenpgp-tools yubikey-manager


export GNUPGHOME=~/.gnupg
wget -O $GNUPGHOME/gpg.conf https://raw.githubusercontent.com/drduh/config/master/gpg.conf

检查系统的熵是否足够(>2000):


$ cat /proc/sys/kernel/random/entropy_avail
3808

将系统切换为离线状态,然后生成密钥。


gpg --expert --full-gen-key
export KEYID=0x57670CCFA42CCF0A

选择 RSA(自定义,只开启 Certify 功能) 并将 keysize 设为 4096,永不过期.

使用旧密钥给新密钥签名


gpg --default-key 0x79A6DE255728228B --sign-key $KEYID
sec rsa4096/0x57670CCFA42CCF0A
created: 2022-01-11 expires: never usage: C
trust: ultimate validity: ultimate
[ultimate] (1). Levi Zim <rsworktech@outlook.com>
gpg: using "0x79A6DE255728228B" as default secret key for signing
sec rsa4096/0x57670CCFA42CCF0A
created: 2022-01-11 expires: never usage: C
trust: ultimate validity: ultimate
Primary key fingerprint: 17AA DD67 26DD C58B 8EE5 8817 5767 0CCF A42C CF0A
Levi Zim <rsworktech@outlook.com>
Are you sure that you want to sign this key with your
key "Believers in Science Studio <rsworktech@outlook.com>" (0x79A6DE255728228B)
Really sign? (y/N) y

然后编辑密钥


gpg --expert --edit-key $KEYID

添加子密钥,分别负责 Sign,Encrypt 和 Authenticate,过期时间一年


addKey

检查密钥


gpg --export $KEYID | hokey lint

然后备份密钥


gpg --export-secret-keys --armor $KEYID > sec-key.key
gpg --export-secret-subkeys --armor $KEYID > sec-sub-key.key

生成撤销证书

导出公钥


gpg --armor --export $KEYID > $KEYID.asc

上传公钥


gpg --send-key $KEYID
gpg --keyserver keys.gnupg.net --send-key $KEYID

修改卡的信息


gpg --card-edit
admin
kdf-setup # Key Derived Function, 从明文传递 PIN 改为验证 PIN 的 Hash
name # 修改姓名
passwd # 修改 PIN, Admin PIN 和 Reset Code

修改重试次数


sudo systemctl start pcscd
ykman openpgp access set-retries 6 6 6
ykman openpgp info

导入 YubiKey(只导入 sub-key)


gpg --edit-key $KEYID
依次选择各个 sub-key,执行 keytocard

然后把 secret key 删除,确保主密钥离线


gpg --delete-secret-key $KEYID

然后测试一下能否正常使用


$ echo "test message string" | gpg --encrypt --armor --recipient $KEYID -o encrypted.txt
$ gpg --decrypt --armor encrypted.txt
gpg: anonymous recipient; trying secret key 0x6F64DD2F6896007A ...
gpg: okay, we are the anonymous recipient.
gpg: encrypted with RSA key, ID 0x0000000000000000
test message string
$ echo "test message string" | gpg --armor --clearsign > signed.txt
$ gpg --verify signed.txt
gpg: Signature made 2022年01月11日 星期二 12时56分17秒 CST
gpg: using RSA key 289670F91C3635F0A17424456F3B98D42FC6C9D8
gpg: Good signature from "Levi Zim <rsworktech@outlook.com>" [ultimate]
Primary key fingerprint: 17AA DD67 26DD C58B 8EE5 8817 5767 0CCF A42C CF0A
Subkey fingerprint: 2896 70F9 1C36 35F0 A174 2445 6F3B 98D4 2FC6 C9D8

Git


git config --global user.signingkey $KEYID

测试


mkdir testing
cd testing
git init
touch woman
git add woman
git commit -sm "Test signing"
git log --show-signature
commit 1e2fe949c5eb0606e083f50b13963814c9a03437 (HEAD -> main)
gpg: Signature made 2022年01月11日 星期二 13时25分07秒 CST
gpg: using RSA key 289670F91C3635F0A17424456F3B98D42FC6C9D8
gpg: Good signature from "Levi Zim <rsworktech@outlook.com>" [ultimate]
Primary key fingerprint: 17AA DD67 26DD C58B 8EE5 8817 5767 0CCF A42C CF0A
Subkey fingerprint: 2896 70F9 1C36 35F0 A174 2445 6F3B 98D4 2FC6 C9D8
Author: kxxt <rsworktech@outlook.com>
Date: Tue Jan 11 13:25:07 2022 +0800
Test signing
Signed-off-by: kxxt <rsworktech@outlook.com>

另外要把公钥添加到 Github.

设置需要触摸 YubiKey 才能触发操作

设置为 cached 会有 15s 的缓存时间,若设置为 on 则不会缓存


ykman openpgp keys set-touch aut on
ykman openpgp keys set-touch sig cached
ykman openpgp keys set-touch enc cached

SSH

编辑 .zshrc

加入


export GPG_TTY="$(tty)"
export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
gpgconf --launch gpg-agent

然后 source .zshrc, 运行 ssh-add -L

把输出拷贝到服务器的 authorized_keys 文件里,就可以连接服务器了

另外把输出也加入到 Github 的 SSH keys 里,就可以通过 SSH 使用 Github 了。

对于现有的 ssh 私钥,也可以导入到 GPG 中


ssh-add ~/.ssh/id_rsa

注意在导入之后应该把原来的私钥删除

安装厂家提供的工具


sudo pacman -S yubikey-personalization yubikey-personalization-gui

(我装了,但是暂时还没用到)

配置 PAM

配置 PAM 之后。 YubiKey 可用于登录和提权等敏感操作

参考:https://wiki.archlinux.org/title/Universal_2nd_Factor#Installing_the_PAM_module


sudo pacman -S pam-u2f


mkdir ~/.config/Yubico
pamu2fcfg -N -o pam://laptop -i pam://laptop > ~/.config/Yubico/u2f_keys

Warning

注意这里 laptop 是我的主机名,读者需要把它换成自己的主机名

另外,这里加上 -N 表示需要输入 Pin, 若不需要,可以把 -N 去掉

Sudo

为了防止误操作而失去 root 权限,我们提前在另一个窗口(或 Tab)运行 sudo -s,以便在配置出现错误时我们能够改正。

编辑 /etc/pam.d/sudo:

在第一行添加:


auth sufficient pam_u2f.so cue origin=pam://laptop appid=pam://laptop

注意,这里我使用的是 sufficient 而非 required, 简单的讲,在这里他们的区别如下:

  • sufficient: 可以使用 U2F 登录,也可以使用密码登录
  • required: 必须使用 U2F 登录

然后使用 sudo uname 测试一下

注意 FIDO 的 PIN 有重试上限,连续三次出错之后必须拔出设备重新插入,连续八次出错之后 FIDO 功能会被锁定!

GDM(Gnome Desktop Manager)

编辑 /etc/pam.d/gdm-password , 在开头添加


auth sufficient pam_u2f.so cue origin=pam://laptop appid=pam://laptop

然后注销再重新登录来测试一下。

Attention

注意: 在 sufficient 的情况下设置 nouserok 会造成安全漏洞,导致不使用 u2f 的用户(比如 root)可以不经认证的登录!

以上设置是针对的既可以使用密码登录,又可以使用 YubiKey 登录这种情形配置的。

如果您需要更强的安全性(必须使用密码登录+YubiKey 登录双重认证),则应该如下设置:

在文件的所有 auth 开头的行之后添加


auth required pam_u2f.so nouserok cue origin=pam://laptop appid=pam://laptop

完蛋,你害得我进不去桌面了,怎么办

进 TTY 去修改配置文件,然后重试

在 Windows 上设置

导入公钥


gpg --import --armor D:\0x57670CCFA42CCF0A.asc

信任密钥


gpg --edit-key 57670CCFA42CCF0A
> trust

设置 Git 签名用的密钥


git config --global user.signingkey 57670CCFA42CCF0A

修改 %APPDATA%/gnupg/gpg-agent.conf , 追加


enable-ssh-support
enable-putty-support

然后重启 agent


gpg-connect-agent killagent /bye
gpg-connect-agent /bye

设置 agent 开机启动:在 shell:startup 中新建一个快捷方式,填入如下指令:


gpg-connect-agent /bye

在快捷方式属性中修改运行方式为最小化,以免开机出现烦人的弹窗

这时候已经可以使用 Putty 连接服务器了

另外,设置 Git 使用 Putty 的 plink :

编辑系统环境变量,设置 GIT_SSHC:\Program Files\PuTTY\plink.exe

设置 Git 使用 Gpg4Win 的 gpg,编辑 ~\.gitconfig , 添加


[gpg]
program = C:/Program Files (x86)/GnuPG/bin/gpg.exe

现在 Git 的 SSH 协议 也可以通过 gpg 来使用了

Tip

我在使用时发现第一次连接时无法选择接受 server 的 fingerprint,

即,在如下状态出现是否要将 key 储存在 cache 中时,无论是按 y 还是按 n 抑或是加上 Enter 都没有反应


git clone git@github.com:kxxt/kxxt
Cloning into 'kxxt'...https://github.com/Yubico/pam-u2f/issues/144
The server's host key is not cached. You have no guarantee
that the server is the computer you think it is.
The server's ssh-ed25519 key fingerprint is:
ssh-ed25519 255 SHA256:+DiY3wvvV6TuJJhbpZisF/zLDA0zPMSvHdkr4UvCOqU
If you trust this host, enter "y" to add the key to
PuTTY's cache and carry on connecting.
If you want to carry on connecting just once, without
adding the key to the cache, enter "n".
If you do not trust this host, press Return to abandon the
connection.
Store key in cache? (y/n, Return cancels connection, i for more info) fatal: Could not read from remote repository.

这个问题可以通过以下方式解决:

先直接使用 plink 连接 GitHub 一次


& 'C:\Program Files\PuTTY\plink.exe' git@github.com

这时选择 y 是有效的,之后再使用 Git 就可以了

如果要在 WSL 中使用 GPG 智能卡, 可以参考我的下一篇文章:https://kxxt.me/blog/wsl-and-gpg-card/

在 Android 上设置

Open Key Chain

打开 OpenKeyChain,导入自己的公钥。

因为我已经把密钥上传到了 keys.openpgp.org, 所以可以通过邮箱直接搜索到。

在导入之后,核对 fingerprint, (页面右上角菜单> “Confirm with fingerprint”)

Termbot

在右上角菜单中点击 “Manage PubKeys”,点击添加,选择 “Add OpenPGP” security key,根据提示操作即可。

添加主机时选择 Yubikey 即可在连接时通过 NFC 验证

两步验证

登录各大网站设置即可

References