前言

  • 不得不承认这个标题有点长,简单而言本文将会讲述如何将 GPG Key 存储到一枚 Yubikey 上,以及如何使用 GPG Key 认证 SSH 登录。
  • 使用 Yubikey 的主要原因有两个:
    第一是可以防止密钥被复制,因为存储在 Yubikey 上的密钥只能被使用却无法被读取。
    第二是存储在 Yubikey 上的密钥被使用时需要触碰确认 (当 Yubikey 亮灯时),可以防止程序在没有通知用户的情况下使用密钥。
  • 注:
    文中代码中高亮部分为 shell command 或者需要手动输入的内容。
    本文使用 gpg-agent (代替 ssh-agent) 以及 Yubikey 的 OpenPGP 功能,而不是直接使用 ssh-agent 以及 Yubikey 的 PIV 功能。
    生成的密钥类型请选择 RSA (4096 bit),因为目前为止 Yubikey 尚不支持存储 ECC GPG KEY最新的 Yubikey 已经支持椭圆曲线 (ECC)。

生成 GPG Key

在内存上建立临时目录

tempdir=$(mktemp -p /dev/shm/ -d)
mkdir $tempdir/gnupg
chmod 700 $tempdir/gnupg

生成 Master Key

注意:这里建议保留 Master Key 的签名功能,因为当更换新的 GPG Key 的时候需要用 Master Key 签署转移声明 (transition statement)。

gpg --homedir $tempdir/gnupg --expert --full-gen-key
gpg (GnuPG) 2.2.17; Copyright (C) 2019 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.

gpg: keybox '/dev/shm/tmp.Mbtak9lidd/gnupg/pubring.kbx' created
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)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
   (9) ECC and ECC
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (13) Existing key
Your selection? 8

Possible actions for a RSA key: Sign Certify Encrypt Authenticate
Current allowed actions: Sign Certify 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 Certify Encrypt Authenticate
Current allowed actions: Sign Certify

   (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) 0
Key does not expire at all
Is this correct? (y/N) y

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

Real name: Example
Email address: e@example.com
Comment:
You selected this USER-ID:
    "Example <e@example.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: /dev/shm/tmp.Mbtak9lidd/gnupg/trustdb.gpg: trustdb created
gpg: key CDB372C7CDB325F5 marked as ultimately trusted
gpg: directory '/dev/shm/tmp.Mbtak9lidd/gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/dev/shm/tmp.Mbtak9lidd/gnupg/openpgp-revocs.d/56C22FDFCDAC7A04DEB51A93CDB372C7CDB325F5.rev'
public and secret key created and signed.

Note that this key cannot be used for encryption.  You may want to use
the command "--edit-key" to generate a subkey for this purpose.
pub   rsa4096 2000-01-01 [SC]
      56C22FDFCDAC7A04DEB51A93CDB372C7CDB325F5
uid                      Example <e@example.com>

这样就生成了完 master key 了,而它的 Fingerprint 为 56C22FDFCDAC7A04DEB51A93CDB372C7CDB325F5

(可选) 撤销证书

撤销证书可以用于声明 GPG Key 不再有效,生成 Master Key 的时候默认会在 openpgp-revocs.d 目录下生成一个,如果有需求可以再额外生成一个并存储到一个安全的位置。

gpg --homedir $tempdir/gnupg --gen-revoke 56C22FDFCDAC7A04DEB51A93CDB372C7CDB325F5 > /Another/Safe/Place/revoke.txt

sec  rsa4096/CDB372C7CDB325F5 2000-01-01 Example <e@example.com>

Create a revocation certificate for this key? (y/N) y
Please select the reason for the revocation:
  0 = No reason specified
  1 = Key has been compromised
  2 = Key is superseded
  3 = Key is no longer used
  Q = Cancel
(Probably you want to select 1 here)
Your decision? 0
Enter an optional description; end it with an empty line:
>
Reason for revocation: No reason specified
(No description given)
Is this okay? (y/N) y
ASCII armored output forced.
Revocation certificate created.

Please move it to a medium which you can hide away; if Mallory gets
access to this certificate he can use it to make your key unusable.
It is smart to print this certificate and store it away, just in case
your media become unreadable.  But have some caution:  The print system of
your machine might store the data and make it available to others!

生成 Sub Key

下一步是生成三种 Sub Key (Signature, Encryption, Authentication),这里选择直接用 GnuPG 生成而不是在 Yubikey 上生成,主要原因是 Yubikey 上生成的密钥无法被读取出来,也就是说没法备份。所以一旦 Yubikey 丢失就会导致所有被加密的数据都再也无法读取,同时这也限制了向多枚 Yubikey 导入相同密钥的可能性。

生成 Signature Key

使用选项 4 可以生成 RSA 签名密钥。

gpg --homedir $tempdir/gnupg --expert --edit-key 56C22FDFCDAC7A04DEB51A93CDB372C7CDB325F5
gpg (GnuPG) 2.2.17; Copyright (C) 2019 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.

Secret key is available.

sec  rsa4096/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
[ultimate] (1). Example <e@example.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 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) 0
Key does not expire at all
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/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
[ultimate] (1). Example <e@example.com>

gpg> save

生成 Encryption Key

使用选项 6 可以生成 RSA 加密密钥。

gpg --homedir $tempdir/gnupg --expert --edit-key 56C22FDFCDAC7A04DEB51A93CDB372C7CDB325F5
gpg (GnuPG) 2.2.17; Copyright (C) 2019 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.

Secret key is available.

sec  rsa4096/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
[ultimate] (1). Example <e@example.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? 6
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) 0
Key does not expire at all
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/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
ssb  rsa4096/7A2FCBDE8C1611AB
     created: 2000-01-01  expires: never       usage: E
[ultimate] (1). Example <e@example.com>

gpg> save

生成 Authentication Key

由于 GnuPG 没有直接提供生成 RSA 认证密钥的选项,所以这时需要自己设定 RSA 密钥所包含的功能。

gpg --homedir $tempdir/gnupg --expert --edit-key 56C22FDFCDAC7A04DEB51A93CDB372C7CDB325F5
gpg (GnuPG) 2.2.17; Copyright (C) 2019 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.

Secret key is available.

sec  rsa4096/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
ssb  rsa4096/7A2FCBDE8C1611AB
     created: 2000-01-01  expires: never       usage: E
[ultimate] (1). Example <e@example.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? 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

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) 0
Key does not expire at all
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/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
ssb  rsa4096/7A2FCBDE8C1611AB
     created: 2000-01-01  expires: never       usage: E
ssb  rsa4096/FD8C0E189EBAB907
     created: 2000-01-01  expires: never       usage: A
[ultimate] (1). Example <e@example.com>

gpg> save

进行备份

由于将 Sub Key 导入 Yubikey 时会删除本地存储的 Sub Key,同时为了安全起见本地最好不存储 Master Key 的私钥以及撤销证书,所以应该先在外部存储留一份备份。

cp $tempdir/gnupg /mnt/USB/gpg_bak

将 Sub Key 导入到 Yubikey

注:Yubikey 默认的 admin PIN 是 12345678

gpgconf --kill gpg-agent
gpg --homedir $tempdir/gnupg --edit-key 56C22FDFCDAC7A04DEB51A93CDB372C7CDB325F5
gpg (GnuPG) 2.2.17; Copyright (C) 2019 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.

Secret key is available.

sec  rsa4096/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
ssb  rsa4096/7A2FCBDE8C1611AB
     created: 2000-01-01  expires: never       usage: E
ssb  rsa4096/FD8C0E189EBAB907
     created: 2000-01-01  expires: never       usage: A
[ultimate] (1). Example <e@example.com>

gpg> toggle

sec  rsa4096/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
ssb  rsa4096/7A2FCBDE8C1611AB
     created: 2000-01-01  expires: never       usage: E
ssb  rsa4096/FD8C0E189EBAB907
     created: 2000-01-01  expires: never       usage: A
[ultimate] (1). Example <e@example.com>

gpg> key 1

sec  rsa4096/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb* rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
ssb  rsa4096/7A2FCBDE8C1611AB
     created: 2000-01-01  expires: never       usage: E
ssb  rsa4096/FD8C0E189EBAB907
     created: 2000-01-01  expires: never       usage: A
[ultimate] (1). Example <e@example.com>

gpg> keytocard
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1

sec  rsa4096/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb* rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
ssb  rsa4096/7A2FCBDE8C1611AB
     created: 2000-01-01  expires: never       usage: E
ssb  rsa4096/FD8C0E189EBAB907
     created: 2000-01-01  expires: never       usage: A
[ultimate] (1). Example <e@example.com>

gpg> key 1

sec  rsa4096/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
ssb  rsa4096/7A2FCBDE8C1611AB
     created: 2000-01-01  expires: never       usage: E
ssb  rsa4096/FD8C0E189EBAB907
     created: 2000-01-01  expires: never       usage: A
[ultimate] (1). Example <e@example.com>

gpg> key 2

sec  rsa4096/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
ssb* rsa4096/7A2FCBDE8C1611AB
     created: 2000-01-01  expires: never       usage: E
ssb  rsa4096/FD8C0E189EBAB907
     created: 2000-01-01  expires: never       usage: A
[ultimate] (1). Example <e@example.com>

gpg> keytocard
Please select where to store the key:
   (2) Encryption key
Your selection? 2

sec  rsa4096/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
ssb* rsa4096/7A2FCBDE8C1611AB
     created: 2000-01-01  expires: never       usage: E
ssb  rsa4096/FD8C0E189EBAB907
     created: 2000-01-01  expires: never       usage: A
[ultimate] (1). Example <e@example.com>

gpg> key 2

sec  rsa4096/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
ssb  rsa4096/7A2FCBDE8C1611AB
     created: 2000-01-01  expires: never       usage: E
ssb  rsa4096/FD8C0E189EBAB907
     created: 2000-01-01  expires: never       usage: A
[ultimate] (1). Example <e@example.com>

gpg> key 3

sec  rsa4096/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
ssb  rsa4096/7A2FCBDE8C1611AB
     created: 2000-01-01  expires: never       usage: E
ssb* rsa4096/FD8C0E189EBAB907
     created: 2000-01-01  expires: never       usage: A
[ultimate] (1). Example <e@example.com>

gpg> keytocard
Please select where to store the key:
   (3) Authentication key
Your selection? 3

sec  rsa4096/CDB372C7CDB325F5
     created: 2000-01-01  expires: never       usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa4096/A63F7DCFA81E0615
     created: 2000-01-01  expires: never       usage: S
ssb  rsa4096/7A2FCBDE8C1611AB
     created: 2000-01-01  expires: never       usage: E
ssb* rsa4096/FD8C0E189EBAB907
     created: 2000-01-01  expires: never       usage: A
[ultimate] (1). Example <e@example.com>

gpg> save

导入完后确认一下。

gpg --card-status
Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240102010006123456780000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 12345678
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: A954 7CD1 06C1 2A39 44D7  D7FB A63F 7DCF A81E 0615
      created ....: 2000-01-01 01:02:03
Encryption key....: 73A2 6539 63AD AE86 87C0  248F 7A2F CBDE 8C16 11AB
      created ....: 2000-01-01 01:02:03
Authentication key: FD5D 7DE0 392C A4D7 5B95  2A8F FD8C 0E18 9EBA B907
      created ....: 2000-01-01 01:02:03
General key info..: [none]

把 GPG Key 从内存里移出来

完成了对 GPG Key 的操作之后,建议删除 Master Key 的私钥,而只保留 Master Key 的公钥即可。

gpg --homedir $tempdir/gnupg --delete-secret-key 56C22FDFCDAC7A04DEB51A93CDB372C7CDB325F5
gpg (GnuPG) 2.2.17; Copyright (C) 2019 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.

sec  rsa4096/CDB372C7CDB325F5 2000-01-01 Example <e@example.com>

Delete this key from the keyring? (y/N) y
This is a secret key! - really delete? (y/N) y

同时删除撤销证书。

rm -r $tempdir/gnupg/openpgp-revocs.d

最后将 gnupg 文件夹从内存移动到 ~/.gnupg。

mv $tempdir/gnupg ~/.gnupg

更改 Yubikey PIN

默认的 user PIN: 123456
默认的 admin PIN: 12345678
注:PIN 可以包含字母,user PIN 为使用 GPG Key 时需要输入的 PIN,而 admin PIN 为对 Yubikey GPG Smartcard 功能进行更改时需要输入的 PIN。

gpg --card-edit

Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240102010006123456780000
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: 12345678
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa4096 rsa4096 rsa4096
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: A954 7CD1 06C1 2A39 44D7  D7FB A63F 7DCF A81E 0615
      created ....: 2000-01-01 01:02:03
Encryption key....: 73A2 6539 63AD AE86 87C0  248F 7A2F CBDE 8C16 11AB
      created ....: 2000-01-01 01:02:03
Authentication key: FD5D 7DE0 392C A4D7 5B95  2A8F FD8C 0E18 9EBA B907
      created ....: 2000-01-01 01:02:03
General key info..: [none]

gpg/card> admin
Admin commands are allowed

gpg/card> passwd
gpg: OpenPGP card no. D2760001240102010006123456780000 detected

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

Your selection? 1
PIN changed.

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

Your selection? 3
PIN changed.

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

Your selection? q

gpg/card> quit

持有人姓名之类的信息也是这里修改,具体可以通过 help 命令来查看。

设置触碰确认

默认情况下使用 Yubikey 的 GPG 功能时是不需要触碰确认的,可以使用 Yubikey Manager 更改设置。

ykman openpgp keys set-touch sig on #签名
ykman openpgp keys set-touch aut on #认证
ykman openpgp keys set-touch dec on #解密

通过 GPG Auth Key 认证 SSH 登录

要通过 GPG Authentication Key 认证 SSH 登录,需要用 gpg-agent 替代 OpenSSH Agent
首先编辑 ~/.gnupg/gpg-agent.conf 添加或修改:

enable-ssh-support
default-cache-ttl-ssh 10800
max-cache-ttl-ssh 10800
pinentry-program /usr/bin/pinentry
# 请根据自己的情况选择 pinentry 程序

然后设置 SSH_AUTH_SOCK 环境变量,使用 XServer 的话可以编辑 ~/.pam_environment

SSH_AUTH_SOCK	DEFAULT="${XDG_RUNTIME_DIR}/gnupg/S.gpg-agent.ssh"

如果使用 wayland 则可以通过 systemd 来设置,新建 `~/.config/environment.d/ssh-auth-sock.conf:

SSH_AUTH_SOCK=${XDG_RUNTIME_DIR}/gnupg/S.gpg-agent.ssh

如果是 Gnome + Wayland 的情况,还需要禁用 GNOME Keyring的 ssh 组件,复制 /etc/xdg/autostart/gnome-keyring-ssh.desktop~/.config/autostart/ 并往里面添加 Hidden=true
完成后重新登录即可即可,之后可以使用 ssh-add -L 列出公钥。
如果还是失败了那么可以从以下方面排查:

  • gpg-agent 是成功运行?
ps aux | grep gpg
systemctl --user list-unit-files | grep gpg-agent

如果没有运行可以通过以下命令开启:

systemctl --user enable --now gpg-agent.service
  • 环境变量(.pam_environment)是否生效?
echo "$SSH_AUTH_SOCK"

如果没有生效可能是由于其他软件的设置冲突导致的,例如 KDE plasma-ssh-agent,以及前文中提到的 Gnome Keyring。

  • 使用 systemctl --user status --now gpg-agent.service ,命令查看错误信息。
  • Yubikey 亮灯时是否通过触碰 Yubikey 确认过操作?

总结

本文其实只涉及了如何生成 GPG Key,将 GPG Key 移动到 Yubikey,以及使用 GPG Authentication Key 来对 SSH 进行认证。而 GPG 的其它用途和设置,例如签名、加密和添加多个身份到同一个 Key 等,以及 Yubikey 的其它用法,例如 U2F 和 PIV 等限于主题和篇幅就不进行探讨了。