Yubikey介绍

官方是这样介绍Yubikey的:

A YubiKey is a small hardware device that offers two-factor authentication with a simple touch of a button. YubiKeys are built strong enough for the largest enterprises, while remaining simple enough for anyone to use. The YubiKey NEO offers both contact (USB) and contactless (NFC, MIFARE) communications. YubiKeys can support FIDO U2F, Yubico-OTP, OATH-OTP, OATH-HOTP, OATH-TOTP, OpenPGP, and PIV, and one security key can support an unlimited number of applications without the need for drivers, client software, or batteries.

U2F

Yubikey的U2F功能开箱即用。

目前支持U2F的浏览器有Chrome, Firefox, Opera。推荐使用Chrome; Firefox需要在浏览器输入about:config然后查找u2f双击这一行启用; Opera没用过不知道是不是需要设置才能使用。

据我所知,目前支持U2F的网站/服务有 :

Google

Facebook

Dropbox

Github

Gitlab

Bitbucket

Fastmail

Lastpass

Dashlane

Keeper

Bitfinex.com

Salesforce

只要根据网站提示开启二次验证(2FA)并绑定你的key, 下次登录账户时,你首先需要像往常一样输入用户名和密码,然后根据提示用你的key进行二次验证。这样即使你的帐号密码被别人知道了,只要key在你手里,那么你的帐号依然是安全的。

OTP

OTP 功能开箱即用 一次一密,需要联网认证,官方有提供认证服务器,当然也可以自己搭建认证服务器。

  • OTP: KEY_ID+AES(AES_KEY, SECRET, COUNT++)即生成的密码包含明文的KEY_ID和对称加密的SECRET和计数器。第一次使用前需要把KEY_ID,AES_KEY,SECRET提交至验证服务器(Yubico提供或者自己搭建),之后应用程序每次通过服务器验证密码的可靠性(解码后SECRET对应、COUNT增大(防止重放攻击))。
  • Static: 静态密码。顾名思义,每次生成固定的一串密码。
  • Challenge-Response: HMAC(SECRET, INPUT)即可以通过HID接口给定一个输入,输入HMAC的计算结果。输入需要本地代码实现。
  • HOTP: HMAC(SECRET, COUNTER++)算法与Challenge-Response类似,然而使用累加计数器代替了输入,并且HTOP是一个标准协议,许多网站和设备都兼容该标准。

每个Yubikey都有两个slot,出厂时默认OTP配置在slot 1,短按操作即可触发OTP认证; slot 2可配置 静态密码 Challenge-Response HOTP 中的一种,长按(2-5s)可触发。

注意yubikey的短按和长按不是指纹识别。

PGP

PGP (Pretty Good Privacy)可能是世界上最优秀的非对称加密工具,公私钥体系真正避免了对称加密会带了的密钥泄漏的问题。而且基于去中心的模型,绕过了 CA,让每个人都能接触到 WOT (Web of Trust)。而 GPG (GNU Privacy Guard)则是 PGP 的开源 GNU 实现。

我们需要把3个PGP子密钥放到key里并使用,实现一定的安全性。

3个子密钥分别是:

S (Signing)

E (Encryption)

A (Authentication)

分别实现签名加密认证功能。建议主密钥只用来生成子密钥使用,生成子密钥后,请先备份好所有的私钥;然后将3个子密钥导入yubikey。从安全角度讲,最好直接在yubikey里生成子密钥,因为yubikey里的密钥是取不出的。但是,凡是都有万一,万一你的yubikey丢了…… 所以,事先离线备份下私钥。

如何生成密钥对?以linux为例

生成密钥对

$gpg2 --full-generate-key
gpg (GnuPG) 2.2.4; Copyright (C) 2017 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

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)
Your selection? 1
## 这里选择默认的RSA密钥对
RSA keys may be between 1024 and 4096 bits long.
What keysize do you want? (2048) 4096
## 我们选择RSA 4096 bit 如果你用的是NEO,请选择2048 bit
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 Sat 12 Jan 2019 09:15:37 PM CST
Is this correct? (y/N) y

GnuPG needs to construct a user ID to identify your key.

Real name: linux
Email address: linux@linuxorg.com
Comment: 
You selected this USER-ID:
    "linux <linux@linuxorg.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: key 00EFA8162571FB59 marked as ultimately trusted
gpg: revocation certificate stored as '/home/linux/.gnupg/openpgp-revocs.d/FC65EF983F06878DCD0B626D00EFA8162571FB59.rev'
public and secret key created and signed.

pub   rsa4096 2018-01-12 [SC] [expires: 2019-01-12]
      FC65EF983F06878DCD0B626D00EFA8162571FB59
uid                      linux <linux@linuxorg.com>
sub   rsa4096 2018-01-12 [E] [expires: 2019-01-12]
## 创建过程结束
## 上面生成了加密子密钥,标识为E;我们开始生成其他的两个密钥

$gpg2 --expert --edit-key 2571FB59
gpg: checking the trustdb
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: depth: 0  valid:   2  signed:   0  trust: 0-, 0q, 0n, 0m, 0f, 2u
gpg: next trustdb check due at 2019-01-12
sec  rsa4096/00EFA8162571FB59
     created: 2018-01-12  expires: 2019-01-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/51EFF717B45316A7
     created: 2018-01-12  expires: 2019-01-12  usage: E   
[ultimate] (1). linux <linux@linuxorg.com>
     
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? 4
## 选择算法 这里仍然选择RSA
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 Sat 12 Jan 2019 09:23:41 PM CST
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/00EFA8162571FB59
     created: 2018-01-12  expires: 2019-01-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/51EFF717B45316A7
     created: 2018-01-12  expires: 2019-01-12  usage: E   
ssb  rsa4096/7FD895A29DBC18B5
     created: 2018-01-12  expires: 2019-01-12  usage: S   
[ultimate] (1). linux <linux@linuxorg.com>
## 此时一个子密钥是E标识 另一个是S标识 下面继续生成A标识
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
## 以上是取消 S E 标识,添加 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 Sat 12 Jan 2019 09:25:34 PM CST
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/00EFA8162571FB59
     created: 2018-01-12  expires: 2019-01-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/51EFF717B45316A7
     created: 2018-01-12  expires: 2019-01-12  usage: E   
ssb  rsa4096/7FD895A29DBC18B5
     created: 2018-01-12  expires: 2019-01-12  usage: S   
ssb  rsa4096/C24EC8048C9A9DC4
     created: 2018-01-12  expires: 2019-01-12  usage: A   
[ultimate] (1). linux <linux@linuxorg.com>
gpg> save

## 至此,我们需要的3个子密钥全部生成完成。
## 主密钥指纹 	00EFA8162571FB59
## 加密子密钥指纹 51EFF717B45316A7
## 签名子密钥指纹 7FD895A29DBC18B5
## 认证子密钥指纹 C24EC8048C9A9DC4
## 我们来看下我们的密钥环
$gpg2 --list-keys
/home/linux/.gnupg/pubring.kbx
--------------------------------
pub   rsa4096 2018-01-12 [SC] [expires: 2019-01-12]
      FC65EF983F06878DCD0B626D00EFA8162571FB59
uid           [ultimate] linux <linux@linuxorg.com>
sub   rsa4096 2018-01-12 [E] [expires: 2019-01-12]
sub   rsa4096 2018-01-12 [S] [expires: 2019-01-12]
sub   rsa4096 2018-01-12 [A] [expires: 2019-01-12]

## 看的更清楚一点
$gpg2 --list-keys --keyid-format LONG
/home/linux/.gnupg/pubring.kbx
--------------------------------
pub   rsa4096/00EFA8162571FB59 2018-01-12 [SC]
      FC65EF983F06878DCD0B626D00EFA8162571FB59
uid                 [ultimate] linux <linux@linuxorg.com>
sub   rsa4096/51EFF717B45316A7 2018-01-12 [E] [expires: 2019-01-12]
sub   rsa4096/7FD895A29DBC18B5 2018-01-12 [S] [expires: 2019-01-12]
sub   rsa4096/C24EC8048C9A9DC4 2018-01-12 [A] [expires: 2019-01-12]
## 这里有个问题,我的主密钥是1年有效期,难不成每年都来一套? 
$ gpg2 --expert --edit-key 2571FB59
sec  rsa4096/00EFA8162571FB59
     created: 2018-01-12  expires: 2019-01-12  usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/51EFF717B45316A7
     created: 2018-01-12  expires: 2019-01-12  usage: E   
ssb  rsa4096/7FD895A29DBC18B5
     created: 2018-01-12  expires: 2019-01-12  usage: S   
ssb  rsa4096/C24EC8048C9A9DC4
     created: 2018-01-12  expires: 2019-01-12  usage: A   
[ultimate] (1). linux <linux@linuxorg.com>

gpg> expire 
Changing expiration time for the primary key.
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

sec  rsa4096/00EFA8162571FB59
     created: 2018-01-12  expires: never       usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/51EFF717B45316A7
     created: 2018-01-12  expires: 2019-01-12  usage: E   
ssb  rsa4096/7FD895A29DBC18B5
     created: 2018-01-12  expires: 2019-01-12  usage: S   
ssb  rsa4096/C24EC8048C9A9DC4
     created: 2018-01-12  expires: 2019-01-12  usage: A   
[ultimate] (1). linux <linux@linuxorg.com>
gpg> save
## 好了,这样主密钥永不过期。每年只需要更新子密钥即可。

PGP加固(optional)

编辑或者添加 ~/.gnupg/gpg.conf文件

auto-key-locate keyserver
#keyserver hkps://hkps.pool.sks-keyservers.net
#keyserver-options no-honor-keyserver-url
#keyserver-options ca-cert-file=/etc/sks-keyservers.netCA.pem
#keyserver-options no-honor-keyserver-url
#keyserver-options debug
#keyserver-options verbose
personal-cipher-preferences AES256 AES192 AES CAST5
personal-digest-preferences SHA512 SHA384 SHA256 SHA224
default-preference-list SHA512 SHA384 SHA256 SHA224 AES256 AES192 AES CAST5 ZLIB BZIP2 ZIP Uncompressed
cert-digest-algo SHA512
s2k-cipher-algo AES256
s2k-digest-algo SHA512
charset utf-8
fixed-list-mode
no-comments
no-emit-version
keyid-format 0xlong
list-options show-uid-validity
verify-options show-uid-validity
with-fingerprint
use-agent
require-cross-certification

备份私钥

$gpg2 --armor --output public.asc --export 2571fb59
## 导出主密钥公钥
$gpg2 --armor --output private.asc --export-secret-keys 2571fb59
##  导出主密钥私钥 需要提供密码
$gpg2 --armor --output private-subkeys.asc --export-secret-subkeys 2571fb59
## 导出子密钥私钥 需要提供密码

## 然后把这三个文件放到一个你认为安全的地方,比如加密后放到Dropbox,存到U盘锁在抽屉里...

上传公钥

$gpg2 --keyserver hkp://pgp.mit.edu --send-keys 2571fb59

这样就把公钥信息上传到pgp.mit.edu,通过交换机制,所有公钥服务器最终都会有你的公钥信息。

设置OPENPGP卡

yubikey 有3个密码 PIN, admin PIN, reset code

默认PIN密码:123456

默认admin PIN密码: 12345678

请牢记

初始化yubikey

$gpg2 --card-edit
gpg/card> admin
Admin commands are allowed
## 进入管理模式
gpg/card> passwd 
gpg: OpenPGP card no. D27600012401020100060XXXXXXX0000 detected

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 1
PIN changed.
## 首先输入默认PIN密码123456 然后输入两次新密码(不低于6位)

1 - change PIN
2 - unblock PIN
3 - change Admin PIN
4 - set the Reset Code
Q - quit

Your selection? 3
## 同样的方法修改admin PIN(不低于8位)
Your selection? q
## help 命令查看更多可用指令
## 其他信息也可以填写 其中url建议保存公钥信息网址 建议填写 
gpg/card> q

错误解析:

gpg2 –import 提示错误 permission denied

解决: echo "export GPG_TTY=$(tty)" >> ~/.bashrc

gpg2 –card-edit 当change PIN时候提示错误

解决:

使用命令 gpg2 --pinentry-mode loopback --card-edit

或者

echo "pinentry-mode loopback" >> ~/.gnupg/gpg.conf

导入私钥到yubikey

$gpg2 --edit-key 2571fb59
sec  rsa4096/00EFA8162571FB59
     created: 2018-01-12  expires: never       usage: SC  
     trust: ultimate      validity: ultimate
ssb  rsa4096/51EFF717B45316A7
     created: 2018-01-12  expires: 2019-01-12  usage: E   
ssb  rsa4096/7FD895A29DBC18B5
     created: 2018-01-12  expires: 2019-01-12  usage: S   
ssb  rsa4096/C24EC8048C9A9DC4
     created: 2018-01-12  expires: 2019-01-12  usage: A   
[ultimate] (1). linux <linux@linuxorg.com>
gpg> key 1

sec  rsa4096/00EFA8162571FB59
     created: 2018-01-12  expires: never       usage: SC  
     trust: ultimate      validity: ultimate
ssb* rsa4096/51EFF717B45316A7
     created: 2018-01-12  expires: 2019-01-12  usage: E   
ssb  rsa4096/7FD895A29DBC18B5
     created: 2018-01-12  expires: 2019-01-12  usage: S   
ssb  rsa4096/C24EC8048C9A9DC4
     created: 2018-01-12  expires: 2019-01-12  usage: A   
[ultimate] (1). linux <linux@linuxorg.com>
## 此时注意看 多了一个* 表示此key被选中
gpg> keytocard 
Please select where to store the key:
   (2) Encryption key
Your selection? 2

## 导入后 再次执行 key 1 反选

## 依次导入key 2 和 key 3
gpg> save
## 这样就可以了 私钥信息不能提取出来,这就是为什么钥先备份再导入的原因

测试

## 首先删除本地信息
$gpg2 --delete-secret-keys 2571FB59
$gpg2 --delete-keys 2571FB59

## 如果你之前在url字段设置了自己公钥信息地址
$gpg2 --card-edit
gpg/card> fetch
gpg/card> q
## 此时就可以查看到信息
$gpg2 --card-status

Yubikey重置

方法一:

$gpg2 --card-edit
gpg/card> admin
Admin commands are allowed
gpg/card> factory-reset

方法二:

官方文档

SSH via PGP

可以将PGP公钥信息转换成SSH格式

$gpg2 --export-ssh-key 2571fb59
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC3PSouOM2gALjoHMroM6p/FdH5FmUXju7p5mnGBGVEIRhq9f8GHsoBjzmFw3gkM+tc7bvThmSVM9jFk0E1C5lE//jNRAzm94OWO1g2MBwEBeaNUsa1CEipgxOl5EnRLr+0hAr65TgQ9iVbxJRP/q9l8jx+4/zangzD76Bu0dc4kVtJsoiGvnvtfIjvAqQMzZw1Sbws7EDmbGCa2+93eTjlVoba9zA6lx8DOeRMjZ0fOXstlGxVWj52JA2Y+ZySAQR4FQUOub7rklxNnYg6dckP9cCtJ6x9r8VtHzcpjUy16pmGZIjLFc+5r0wEYbsR2v6xB0G/mf3g+qPNZ3uMlqSYhUNnINMbh1cbVsTqaXQzWtcJP9k4+LaAzglRgV0jSCCQou3yb0MKmMPgUHtYwqeffHQk78CAWbWz3k+uXxFmx0WN++P5jj19p72llm820erfl2lG9zG5AUCyc/BV52FPefyNU3AQRi99+dN5qt2dMOTQ2YhpAzgL7Pj5D5zk3qck7HGrT3uu90mnguPRkAA+MuZivdWapE3lW/a4GXeWYslIEBKcqyHsODt4cC+RAflLE5bTTaWqemaCeYgPGtVjjjfQbZVkKOfdujRsrKM1f4ruujaxYSSzx4ahOsPem76zfJ8sSjgVshoJBBMAvN+7u+tOLqjgv6DtdT6whMjhLw== openpgp:0x8C9A9DC4

上面命令输出的即是SSH格式的PGP认证信息。 将以上信息输出到 ~/.ssh/id_rsa.pub,然后复制到目标机器的authorized_keys, 即可利用PGP实现SSH认证。

$gpg2 --export-ssh-key 2571fb59 >> ~/.ssh/id_rsa.pub
$ssh-copy-id [user@]hostname

事实上还是ssh的功能,默认的ssh认证使用的是ssh-agent,这里只不过使用gpg-agent代替ssh-agent完成认证。

要通过gpg-agent实现ssh-agent的功能,还需要编辑两个文件

Shell rc文件 ~/.bashrc 或者 ~/.zshrc

# for GPG
if [ -f "${HOME}/.gpg-agent-info" ]; then
	. "${HOME}/.gpg-agent-info"
	export GPG_AGENT_INFO
	export SSH_AUTH_SOCK
	export SSH_AGENT_PID
fi

export GPG_TTY=$(tty)
# for Arch Linux
 export SSH_AUTH_SOCK=$(gpgconf --list-dirs agent-ssh-socket)
 gpg-connect-agent updatestartuptty /bye

# for linux
# export SSH_AUTH_SOCK="${HOME}/.gnupg/S.gpg-agent.ssh"
# gpgconf --launch gpg-agent

~/.gnugp/gpg-agent.conf

enable-ssh-support
default-cache-ttl 1800
max-cache-ttl 3600
write-env-file
use-standard-socket

之后logoff或者重启机器

PAM模块

PAM (Pluggable Authentication Module)

官方文档

Arch用户直接从AUR安装pam_u2f

$sudo pacman -S libu2f-host
$yaourt -S libu2f-server pam_u2f

配置:

注册设备

pamu2fcfg -u<username>

这时 Yubikey 上的LED会闪烁提示,轻触 输出格式如下

<username>:<KeyHandle1>,<UserKey1>

将输出的内容放到 ~/.config/Yubico/u2f_keys

编辑需要的PAM模块(sudo为例)

auth sufficient pam_u2f.so cue

加cue参数会打印一行话提示你轻触Yubikey进行验证

附pamu2fcfg用法

OPTIONS
debug 
Enables debug output

debug_file 
Filename to write debug to, file must exist and be a regular file. STDERR is default

origin=origin 
Set the origin for the U2F authentication procedure. If no value is specified, the origin "pam://$HOSTNAME" is used.

appid=appid 
Set the application ID for the U2F authentication procedure. If no value is specified, the same value used for origin is taken ("pam://$HOSTNAME" if also origin is not specified).

authfile=file 
Set the location of the file that holds the mappings of user names to keyHandles and user keys. The format is username:keyHandle1,public_key1:keyHandle2,public_key2:… the default location of the file is $XDG_CONFIG_HOME/Yubico/u2f_keys. If the environment variable is not set, $HOME/.config/Yubico/u2f_keys is used.

nouserok 
Set to enable authentication attempts to succeed even if the user trying to authenticate is not found inside authfile or if authfile is missing/malformed.

openasuser 
Setuid to the authenticating user when opening the authfile. Useful when the user’s home is stored on an NFS volume mounted with the root_squash option (which maps root to nobody which will not be able to read the file).

alwaysok 
Set to enable all authentication attempts to succeed (aka presentation mode).

max_devices=n_devices
Maximum number of devices allowed per user (default is 24). Devices specified in the authentication file that exceed this value will be ignored.

interactive 
Set to prompt a message and wait before testing the presence of a U2F device. Recommended if your device doesn’t have tactile trigger.

[prompt=your prompt here] 
Set individual prompt message for interactive mode. Watch the square brackets around this parameter to get spaces correctly recognized by PAM.

manual 
Set to drop to a manual console where challenges are printed on screen and response read from standard input. Useful for debugging and SSH sessions without U2F-support from the SSH client/server. If enabled, interactive mode becomes redundant and has no effect.

cue 
Set to prompt a message to remind to touch the device.

PIV

To do

Reference:

  1. https://developers.yubico.com/PGP/Importing_keys.html
  2. https://www.yubico.com/support/knowledge-base/categories/articles/reset-applet-yubikey/#resetapplet
  3. https://wiki.archlinux.org/index.php/Yubikey
  4. https://www.esev.com/blog/post/2015-01-pgp-ssh-key-on-yubikey-neo/
  5. https://github.com/drduh/YubiKey-Guide
  6. https://gist.github.com/ageis/14adc308087859e199912b4c79c4aaa4

本文采用 知识共享署名 4.0 国际许可协议(CC-BY 4.0)进行许可。转载请注明来源: https://snowfrs.com/yubikey 欢迎对文中引用进行考证,欢迎指出任何不准确和模糊之处。