# YubiKey

YubiKey (opens new window)Yubico社 (opens new window)のハードウェア認証デバイスで、種々の認証プロトコルに対応しています。

本稿では、2020年7月に購入したYubiKey 5 NFC (opens new window)[1]でOpenPGPを試してみます。

パッケージに入ったYubiKey 5 NFC

# インストール

Xubuntu 20.04では、デフォルトでインストールされているgpgパッケージの他に、スマートカードとのやりとりのためのデーモンpcscdと、GnuPGにスマートカードのサポートを提供するscdaemonを追加でインストールする必要がありました。pcscdのためにlibccidもインストールされました。

$ sudo apt install pcscd scdaemon

# YubiKeyの接続

USBポートにYubiKey 5 NFCを接続します。dmesgコマンドで確認すると、入力デバイスとして認識されたことがわかります。

usb 5-1: new full-speed USB device number 6 using xhci_hcd
usb 5-1: New USB device found, idVendor=1050, idProduct=0407, bcdDevice= 5.26
usb 5-1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 5-1: Product: YubiKey OTP+FIDO+CCID
usb 5-1: Manufacturer: Yubico
input: Yubico YubiKey OTP+FIDO+CCID as /devices/pci0000:00/0000:00:07.1/0000:0a:00.3/usb5/5-1/5-1:1.0/0003:1050:0407.0007/input/input24
hid-generic 0003:1050:0407.0007: input,hidraw4: USB HID v1.10 Keyboard [Yubico YubiKey OTP+FIDO+CCID] on usb-0000:0a:00.3-1/input0
hid-generic 0003:1050:0407.0008: hiddev0,hidraw5: USB HID v1.10 Device [Yubico YubiKey OTP+FIDO+CCID] on usb-0000:0a:00.3-1/input1

GnuPGからはスマートカードとして認識されます。シリアル番号は隠してあります。

$ gpg --card-status
Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240103040006********0000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: ********
Name of cardholder: [not set]
Language prefs ...: [not set]
Salutation .......:
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa2048 rsa2048 rsa2048
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 0
KDF setting ......: off
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

ここからは、Yubicoによる文書Using Your YubiKey with OpenPGP (opens new window)を参考に進めます。

# OpenPGP鍵対の生成

OpenPGP鍵対を生成しておきます。GnuPGによる鍵対の生成と管理を参照してください。

# 私有鍵のバックアップの作成

YubiKeyに移動してしまった私有鍵は取り出すことができません。YubiKeyを壊してしまった場合に私有鍵が失なわれてしまわないように、バックアップを作成しておくこともできます。安全な場所に保管しておきましょう。

マスター鍵対のIDの例として、ここではF60960D80B224382CA8D831CB56C20316D6E8279を利用します。手元の鍵対のIDで置き換えてください。

$ gpg --export-secret-key --armor F60960D80B224382CA8D831CB56C20316D6E8279

パスフレーズを入力すると、ASCII Armor形式で私有鍵が表示されます。安全な場所に保管してください。

# YubiKeyへの私有鍵の移動

YubiKey 5 NFCをUSBポートに接続したまま操作を進めます。gpg --edit-keyコマンドを起動します。

$ gpg --edit-key F60960D80B224382CA8D831CB56C20316D6E8279
gpg (GnuPG) 2.2.19; 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  rsa3072/B56C20316D6E8279
     created: 2020-06-24  expires: 2022-06-24  usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa3072/164F21FF001C8CD1
     created: 2020-06-24  expires: 2022-06-24  usage: E
[ultimate] (1). zunda <zundan@gmail.com>

まず主鍵をYubiKeyの署名鍵スロットに移動します。私有鍵のパスフレーズを入力した後、YubiKeyのAdmin PIN (デフォルト (opens new window)では12345678)を入力します。

gpg> keytocard
Really move the primary key? (y/N) y
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 1

Admin PINの入力

主鍵をYubiKeyの認証鍵スロットにも移動します。

gpg> keytocard
Really move the primary key? (y/N) y
Please select where to store the key:
   (1) Signature key
   (3) Authentication key
Your selection? 3

sec  rsa3072/B56C20316D6E8279
     created: 2020-06-24  expires: 2022-06-24  usage: SC
     trust: ultimate      validity: ultimate
ssb  rsa3072/164F21FF001C8CD1
     created: 2020-06-24  expires: 2022-06-24  usage: E
[ultimate] (1). zunda <zundan@gmail.com>

次に暗号鍵をYubiKeyの暗号鍵スロットに移動します。

gpg> key 1

sec  rsa3072/B56C20316D6E8279
     created: 2020-06-24  expires: 2022-06-24  usage: SC
     trust: ultimate      validity: ultimate
ssb* rsa3072/164F21FF001C8CD1
     created: 2020-06-24  expires: 2022-06-24  usage: E
[ultimate] (1). zunda <zundan@gmail.com>

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

sec  rsa3072/B56C20316D6E8279
     created: 2020-06-24  expires: 2022-06-24  usage: SC
     trust: ultimate      validity: ultimate
ssb* rsa3072/164F21FF001C8CD1
     created: 2020-06-24  expires: 2022-06-24  usage: E
[ultimate] (1). zunda <zundan@gmail.com>

最後に移動した鍵を~/.gnupg/から取り除いて終了します。

gpg> quit
Save changes? (y/N) y

私有鍵がYubiKeyに移動された(secssbの後ろに>マークがある)ことを確認します。

$ gpg --list-secret-keys
/home/zunda/.gnupg/pubring.kbx
------------------------------
sec>  rsa3072 2020-06-24 [SC] [expires: 2022-06-24]
      F60960D80B224382CA8D831CB56C20316D6E8279
      Card serial no. = 0006 ********
uid           [ultimate] zunda <zundan@gmail.com>
ssb>  rsa3072 2020-06-24 [E] [expires: 2022-06-24]

公開鍵のURLを登録しておきます。

$ gpg --card-edit
gpg/card> admin
Admin commands are allowed
gpg/card> url
URL to retrieve public key: https://keys.openpgp.org/vks/v1/by-fingerprint/F60960D80B224382CA8D831CB56C20316D6E8279
gpg/card> quit

YubiKeyのOpenPGPアプレットの状態も確認できます。デジタル署名を生成した回数も記録されているようです。

$ gpg --card-status
Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240103040006********0000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: ********
Name of cardholder: [not set]
Language prefs ...: [not set]
Salutation .......:
URL of public key : https://keys.openpgp.org/vks/v1/by-fingerprint/F60960D80B224382CA8D831CB56C20316D6E8279
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa3072 rsa2048 rsa3072
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 7
KDF setting ......: off
Signature key ....: F609 60D8 0B22 4382 CA8D  831C B56C 2031 6D6E 8279
      created ....: 2020-06-24 05:26:57
Encryption key....: CAE6 B476 3A84 A557 2636  25CE 164F 21FF 001C 8CD1
      created ....: 2020-06-24 05:26:57
Authentication key: F609 60D8 0B22 4382 CA8D  831C B56C 2031 6D6E 8279
      created ....: 2020-06-24 05:26:57
General key info..: pub  rsa3072/B56C20316D6E8279 2020-06-24 zunda <zundan@gmail.com>
sec>  rsa3072/B56C20316D6E8279  created: 2020-06-24  expires: 2022-06-24
                                card-no: 0006 ********
ssb>  rsa3072/164F21FF001C8CD1  created: 2020-06-24  expires: 2022-06-24
                                card-no: 0006 ********

# 私有鍵の利用

これまで通りデジタル署名や復号します。私有鍵が必要になった時に、YubiKeyのUSBポートへの接続を求められます。

YubiKeyの接続

YubiKeyを接続して、YubiKeyのUser PIN (デフォルト (opens new window)では123456)を入力します。

YubiKeyのUser PIN

# YubiKeyの設定

PINがデフォルトのままなのは鍵を紛失してしまった場合に心許無いので、変更しておきます。既存のUser PINと新しいUser PINを、GUIから入力します。

$ gpg --card-edit

gpg/card> admin
Admin commands are allowed

gpg/card> passwd
gpg: OpenPGP card no. D2760001240103040006********0000 detected

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

Your selection? 1

同様にAdmin PINを変更します。

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

Your selection? 3

終了します。

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

Your selection? q

gpg/card> q

# 他のLinuxでの私有鍵の利用

Ubuntu 16.04で試してみます。上と同様、まず追加で必要なパッケージをインストールします。デーモンの起動のためにインストール後にログアウトして再ログインしておくと良いでしょう。

$ sudo apt install pcscd scdaemon

Ubuntu 16.04でバージョン2のGnuPGはgpg2コマンドで利用できます。2.1.11がインストールされていました。

まず自分の公開鍵をインポートしておきます。Ubuntu 16.04のGnuPG 2.1.11ではhttpsで公開鍵をインポートすることができないようなので、curlで代用します。

$ curl -s https://keys.openpgp.org/vks/v1/by-fingerprint/F60960D80B224382CA8D831CB56C20316D6E8279 | gpg2 --import
gpg: keybox '/home/zunda/.gnupg/pubring.kbx' created
gpg: /home/zunda/.gnupg/trustdb.gpg: trustdb created
gpg: key 6D6E8279: public key "zunda <zundan@gmail.com>" imported
gpg: Total number processed: 1
gpg:               imported: 1

私有鍵がYubiKeyにあることを、GnuPGに知らせます。YubiKeyをUSBポートに挿入しgpg2 --card-statusコマンドを実行することで、鍵束にスタブが生成され、私有鍵のあるYubiKeyのシリアル番号が記録されます。

$ gpg2 --card-status

Reader ...........: Yubico Yubikey 4 OTP U2F CCID 00 00
Application ID ...: D2760001240103040006********0000
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: ********
Name of cardholder: [not set]
Language prefs ...: [not set]
Sex ..............: unspecified
URL of public key : https://keys.openpgp.org/vks/v1/by-fingerprint/F60960D80B224382CA8D831CB56C20316D6E8279
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa3072 rsa2048 rsa3072
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 9
Signature key ....: F609 60D8 0B22 4382 CA8D  831C B56C 2031 6D6E 8279
      created ....: 2020-06-24 05:26:57
Encryption key....: CAE6 B476 3A84 A557 2636  25CE 164F 21FF 001C 8CD1
      created ....: 2020-06-24 05:26:57
Authentication key: F609 60D8 0B22 4382 CA8D  831C B56C 2031 6D6E 8279
      created ....: 2020-06-24 05:26:57
General key info..: pub  rsa3072/6D6E8279 2020-06-24 zunda <zundan@gmail.com>
sec>  rsa3072/6D6E8279  created: 2020-06-24  expires: 2022-06-24
                        card-no: 0006 ********
ssb#  rsa3072/001C8CD1  created: 2020-06-24  expires: 2022-06-24

YubiKeyの私有鍵で自分の公開鍵に署名しておきます。trustコマンドで5 (I trust ultimately)します。

$ gpg2 --edit-key F60960D80B224382CA8D831CB56C20316D6E8279
gpg (GnuPG) 2.1.11; Copyright (C) 2016 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  rsa3072/6D6E8279
     created: 2020-06-24  expires: 2022-06-24  usage: SC  
     card-no: 0006 ********
     trust: unknown       validity: unknown
sub  rsa3072/001C8CD1
     created: 2020-06-24  expires: 2022-06-24  usage: E   
[ unknown] (1). zunda <zundan@gmail.com>

gpg> trust
sec  rsa3072/6D6E8279
     created: 2020-06-24  expires: 2022-06-24  usage: SC  
     card-no: 0006 ********
     trust: unknown       validity: unknown
sub  rsa3072/001C8CD1
     created: 2020-06-24  expires: 2022-06-24  usage: E   
[ unknown] (1). zunda <zundan@gmail.com>

Please decide how far you trust this user to correctly verify other users' keys
(by looking at passports, checking fingerprints from different sources, etc.)

  1 = I don't know or won't say
  2 = I do NOT trust
  3 = I trust marginally
  4 = I trust fully
  5 = I trust ultimately
  m = back to the main menu

Your decision? 5
Do you really want to set this key to ultimate trust? (y/N) y

sec  rsa3072/6D6E8279
     created: 2020-06-24  expires: 2022-06-24  usage: SC  
     card-no: 0006 ********
     trust: ultimate      validity: unknown
sub  rsa3072/001C8CD1
     created: 2020-06-24  expires: 2022-06-24  usage: E   
[ unknown] (1). zunda <zundan@gmail.com>
Please note that the shown key validity is not necessarily correct
unless you restart the program.

gpg> quit

これで、YubiKeyに移動された私有鍵を、私有鍵を生成したのとは異なる環境で利用できるようになりました。公開鍵の信頼の網は別途確立する必要があります。

Ubuntu 16.04では、Gitでの変更内容へのデジタル署名gpg2コマンドを利用する必要がありそうです。

$ git config --global gpg.program gpg2

Gitで変更内容へデジタル署名してみましょう。

$ git commit -S
[move-yubikey 3a27355] Use YubiKey at a separate environment
 1 file changed, 119 insertions(+)

デジタル署名の検証に成功しました。

$ git verify-commit 3a27355
gpg: Signature made Sun 19 Jul 2020 02:33:49 PM HST using RSA key ID 6D6E8279
gpg: Good signature from "zunda <zundan@gmail.com>" [ultimate]

# 新しいYubiKeyでの既存の鍵対の利用

上記の操作でGnuPGは鍵束にスタブを作成し、私有鍵のあるYubiKeyのシリアル番号を記録しました。新しいYubiKeyを購入した場合など、スタブを更新する場合には、いちどスタブを消去する必要があるようです。下記の操作はUbuntu 22.04で行ないましたので、gpgコマンドでGnuPG 2.2.4が起動されました。操作の結果、gpg --list-secret-keysに対象の私有鍵が表示されなくなりました。

$ gpg --delete-secret-key F60960D80B224382CA8D831CB56C20316D6E8279
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.


sec  rsa3072/B56C20316D6E8279 2020-06-24 zunda <zundan@gmail.com>

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

既存のスタブを消去したあと、新しいYubiKeyをUSBポートに挿入しgpg --card-statusコマンドを実行することで、再度鍵束にスタブが生成され、新しいYubiKeyのシリアル番号が記録されます。

# macOSでの私有鍵の利用

GPG SuiteをインストールしたmacOSでもYubiKeyに格納された私有鍵を利用することができます。

GPG SuiteでインストールされるGPG Keychainで、Lookup KeyからPGP公開鍵サーバに登録した公開鍵を、メールアドレスなどで検索してインポートします。

私有鍵がYubiKeyにあることを、GPG Suiteに知らせます。YubiKeyをUSBポートに挿入しgpg --card-statusコマンドを実行することで、鍵束にスタブが生成され、私有鍵のあるYubiKeyのシリアル番号が記録されます。

$ gpg --card-status
Reader ...........: 1050:0407:X:0
Application ID ...: D2760001240103040006********0000
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: ********
Name of cardholder: [not set]
Language prefs ...: [not set]
Salutation .......:
URL of public key : https://keys.openpgp.org/vks/v1/by-fingerprint/F60960D80B224382CA8D831CB56C20316D6E8279
Login data .......: [not set]
Signature PIN ....: not forced
Key attributes ...: rsa3072 rsa2048 rsa3072
Max. PIN lengths .: 127 127 127
PIN retry counter : 3 0 3
Signature counter : 10
KDF setting ......: off
Signature key ....: F609 60D8 0B22 4382 CA8D  831C B56C 2031 6D6E 8279
      created ....: 2020-06-24 05:26:57
Encryption key....: CAE6 B476 3A84 A557 2636  25CE 164F 21FF 001C 8CD1
      created ....: 2020-06-24 05:26:57
Authentication key: F609 60D8 0B22 4382 CA8D  831C B56C 2031 6D6E 8279
      created ....: 2020-06-24 05:26:57
General key info..: pub  rsa3072/B56C20316D6E8279 2020-06-24 zunda <zundan@gmail.com>
sec>  rsa3072/B56C20316D6E8279  created: 2020-06-24  expires: 2022-06-24
                                card-no: 0006 ********
ssb#  rsa3072/164F21FF001C8CD1  created: 2020-06-24  expires: 2022-06-24

ヒント

環境によっては[2]gpg --card-statusコマンドが、Operation not supported by deviceといったエラーを表示して失敗することがあるようです。YubicoによるTroubleshooting Issues with GPG (opens new window)を参考に、下記の内容のファイルを~/.gnupg/scdaemon.confとして作成して、ラップトップを再起動することでエラーを解消することができました。

shared-access

GPG Keychainで、公開鍵をダブルタップして、Detailsメニューから公開鍵の指紋が自分のものであることを確認して、Owner TrustをUltimateにします。

GPG Keychainでの信頼度の設定

デジタル署名や復号などで私有鍵が必要になった場合には、YubiKeyのUser PINをPinentryに入力します。

Pinentry MacへのPINの入力

# 携帯電話での私有鍵の利用

OpenKeychainなどのアプリケーションをNFCの利用可能な携帯電話インストールすることで、YubiKeyに格納された私有鍵を利用できるようになります。

# エアギャップ環境での鍵対の管理

私有鍵の秘匿性を高めるため、ネットワーク接続のない環境で鍵対を生成しYubiKeyへ保管したい場合があります。このような場合、Tails OS (opens new window)などを利用し、USBフラッシュメモリに収めたOSを起動しネットワークに接続せずに鍵対の生成とYubiKeyの管理が可能です。

2022年5月現在、Tails 5.0では下記のバージョンのパッケージが利用できました。

  • gpg-2.2.27-2+deb11u1
  • scdaemon-2.2.27-2+deb11u1
  • pcscd-1.9.1-1
  • libccid-1.4.34-1
  • paperkey-1.6-1

paperkeyは、生成した私有鍵を紙に印刷するなどしてバックアップしやすい形式に変換するツールです。gpg –export-secret-key | paperkeyなどのコマンド列で利用します。私有鍵がネットワークに露出してしまわないよう、印刷にはUSBなどで直接接続されたプリンタを利用する必要があります。


  1. 2020年9月にはYubiKey 5C NFC (opens new window)が発売されました。コネクタの形状以外はYubiKey 5 NFCと同じ仕様のようです。USB-Cを利用している場合はYubiKey 5C NFCを購入するのが良さそうです。 ↩︎

  2. MacBook Air M1, 2020、macOS Ventura 13.3.1、GPG_Suite-2023.2で確認しました ↩︎