GPG Key セットアップ ~手元PCから秘密鍵を駆逐してやる~

Summary

SSH やクライアント認証に使う鍵が増えてきて、鍵を適切に管理したいけどうまくいかず、混沌を極める Windows をメイン機として使わなければならない社畜の苦労物語である。

はじめに

Windows で安全な公開鍵認証を実現するためには、Windows に秘密鍵ファイルを配置しないことである。

それを実現するためには、従来の方法は PuTTY-CAC を利用して YubiKey にセットした PIV(Personal Identity Verification) を読み出しその秘密鍵を利用して公開鍵認証すればどの PC を使っても秘密鍵を Windows 上に配置せずに実現できる。

だが、前述の通り Windows の OpenSSH 及び プロセス間通信の方法は混沌としており素人が手を出すと時間を溶かし「なんの成果も挙げられませんでした」になり心が粉砕する。(経験談)
そのため筆者が環境構築した方法を備忘録として残し皆さんに「ぼくのかんがえたさいきょうのこうせいれい」として共有する。

本記事の内容で構成すれば、下記のように YubiKey の鍵を使い想定される用途では Windows に鍵を置かずに安全な環境を構築できるはずです。

graph LR subgraph Windows 11 subgraph YubiKey A1(PIV) A2(GPG) end subgraph KeePassXC A3(Private Key) end subgraph gpg-agent G1(NamedPipe) G2(pageant shm) end subgraph Clients C1(Windows OpenSSH) C3(Tera Term,WinSCP) end subgraph WSL2 C2(wsl2-ssh-agent) end end subgraph Remote R1(ssh-agent) end YubiKey --> gpg-agent KeePassXC --> gpg-agent G1 --> C1 G1 --> C2 G2 --> C3 C1 --> R1

GPG 鍵公開について

運用していていくつか問題点が出てきたので更新します。 OpenPGP の公開鍵は一般的に Key Server に登録しておき、それを相手に取得してもらうことで検証が楽になる。 が、旧来の OpenPGP Key Server は「アイデンティティ情報」と「鍵に関するすべての情報」がすべて公開されていた。

  • アイデンティティ情報
    • ユーザーID
      • name
      • email
  • 鍵に関するすべての情報
    • 作成日
    • 有効期限
    • 失効状況
    • メタデータ

OpenPGP 公開鍵サーバにおける公開鍵の汚染問題 が発生したため、 keys.openpgp.org などは key をアップしただけだと「鍵に関するすべての情報」は公開するが「アイデンティティ情報」を公開しない。そのため、https://keyoxide.org などで notation を付与し検証にしようとしても、確認することが出来ない。私の環境では GitHub の非公開 Email で Commit する前提の運用なためこれだと Email の検証が出来ず、 gpg --import などでも ユーザーID が確認出来ないため Import 出来ない。また、 GitHub には 生の公開鍵を登録し keys.openpgp.org にも登録しておくという方法も考えたがこれだと入手するプラットフォームによっては鍵が変化してしまうため良くない。

そのため、私の使い方では GitHub と keybase に登録し ID 証明することにする。

用意するもの

まず、今回は Windows から普段使いの秘密鍵を「駆逐してやる、オレの環境から」を目標としているため、秘密鍵を外部の安全なデバイスに保管する必要があります。また、この鍵に関しては、後ほど GPG (GnuPG) を利用しますが、詳細は非常に膨大な資料となるので割愛します。ざっくり言えば、個人を公開鍵で認証して、メールを暗号化したり、認証してセキュアにするためのものです。

そのため、生成される主鍵 (Master Key) はそれ自体が人格を有していると考えるとわかりやすく、主鍵は絶対に漏洩してはならないものです。漏洩した場合は、公開鍵認証の信用をすべて失うことになります。

最低限として下記を用意した

最終的に男の子が好きそうなスタイルにした

鍵運用について

GPG Key には 主鍵(Master Key)、副鍵(Sub Key) が存在するが、どちらを入れるかで宗派があるようでした。主鍵はそれが本人であることを証明できるためガチで使う場合は必要らしいが、手軽に使う鍵では近年ないため YubiKey には副鍵を入れることにする。

鍵の用途には署名(Sign)、暗号化(Encrypt)、認証(Authenticate)、証明(Certify) があるのでそれぞれを 主鍵、副鍵に割り振る

  • 鍵は強度は基本的に Ed25519 を採用
  • 主鍵(Master Key)
    鍵強度は NIST P-521 にする(考え方的には一生変更が不要なはずのため現時点で一番強度が高い物を選択)
    • 証明(Certify)
  • 副鍵(Sub Key)
    • 署名(Sign)
    • 暗号化(Encrypt)
    • 認証(Authenticate)

副鍵(Sub Key) は複数作成できるが、 YubiKey に格納できる鍵は 署名(Sign)、暗号化(Encrypt)、認証(Authenticate) 各1つとなっている。そのため 認証(Authenticate) 鍵として下位互換性として RSA 2048 の鍵格納したかったのだが叶わず、 PIV Card の方に現在普段使いしている既存の RSA 2048 鍵を設定することですぐにセキュアな環境を作ることにした。

必要パッケージのインストール

1
2
3
4
5
> winget install GnuPG.Gpg4win
> winget install Yubico.YubiKeyManagerCLI

# GPG Key を OpenSSL 形式に変更する場合は必要
> winget install ShiningLight.OpenSSL

作業ディレクトリを作成

通常通り、 gpg コマンドで作業しても良いが、作業が完了し終わって端末から秘密鍵を削除する都合があるため、物理USBデバイスのフォルダーを指定して作業を始めたほうが良いのでそのようにする。

また、一部 Windows の GunPG は GNUPGHOME の環境変数でディレクトリーを変更出来ないという記事があったが当環境の GnuPG.Gpg4win 4.3.1 付属の gpg コマンドでは問題なく設定できた

1
2
3
4
> $env:GNUPGHOME="F:\gnupg"

> New-Item "$env:GNUPGHOME" -ItemType Directory
> Set-Location -Path "$env:GNUPGHOME"

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
> gpg --version
  gpg (GnuPG) 2.4.5
  libgcrypt 1.10.3
  Copyright (C) 2024 g10 Code GmbH
  License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
  This is free software: you are free to change and redistribute it.
  There is NO WARRANTY, to the extent permitted by law.

-  Home: C:\\Users\\naa0yama\\AppData\\Roaming\\gnupg
+  Home: F:\gnupg
  サポートしているアルゴリズム:
  公開鍵: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
  暗号方式: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256,
      TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256
  ハッシュ: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
  圧縮: 無圧縮, ZIP, ZLIB, BZIP2

GPG

主鍵作成

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
+   > gpg --expert --full-gen-key
    gpg (GnuPG) 2.4.5; Copyright (C) 2024 g10 Code GmbH
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.

    ご希望の鍵の種類を選択してください:
    (1) RSA と RSA
    (2) DSA と Elgamal
    (3) DSA (署名のみ)
    (4) RSA (署名のみ)
    (7) DSA (機能をあなた自身で設定)
    (8) RSA (機能をあなた自身で設定)
    (9) ECC (署名と暗号化) *デフォルト
    (10) ECC (署名のみ)
    (11) ECC (機能をあなた自身で設定)
    (13) 既存の鍵
    (14) カードに存在する鍵
+   あなたの選択は? 11

    このECC鍵にありうる操作: Sign Certify Authenticate
    現在の認められた操作: Sign Certify

    (S) 署名機能を反転する
    (A) 認証機能を反転する
    (Q) 完了

+   あなたの選択は? S

    このECC鍵にありうる操作: Sign Certify Authenticate
    現在の認められた操作: Certify

    (S) 署名機能を反転する
    (A) 認証機能を反転する
    (Q) 完了

+   あなたの選択は? q
    ご希望の楕円曲線を選択してください:
    (1) Curve 25519 *デフォルト
    (2) Curve 448
    (3) NIST P-256
    (4) NIST P-384
    (5) NIST P-521
    (6) Brainpool P-256
    (7) Brainpool P-384
    (8) Brainpool P-512
    (9) secp256k1
+   あなたの選択は? 5
    鍵の有効期限を指定してください。
            0 = 鍵は無期限
        <n>  = 鍵は n 日間で期限切れ
        <n>w = 鍵は n 週間で期限切れ
        <n>m = 鍵は n か月間で期限切れ
        <n>y = 鍵は n 年間で期限切れ
+   鍵の有効期間は? (0)0
    鍵は無期限です
+   これで正しいですか? (y/N) y

    GnuPGはあなたの鍵を識別するためにユーザIDを構成する必要があります。

    本名: naa0yama
    電子メール・アドレス: [email protected]
    コメント:
    次のユーザIDを選択しました:
        "naa0yama <[email protected]>"

    名前(N)、コメント(C)、電子メール(E)の変更、またはOK(O)か終了(Q)? o
    たくさんのランダム・バイトの生成が必要です。キーボードを打つ、マウスを動か
    す、ディスクにアクセスするなどの他の操作を素数生成の間に行うことで、乱数生
    成器に十分なエントロピーを供給する機会を与えることができます。
    gpg: ディレクトリ'C:\\Users\\naa0yama\\AppData\\Roaming\\gnupg\\openpgp-revocs.d'が作成されました
    gpg: 失効証明書を 'C:\\Users\\naa0yama\\AppData\\Roaming\\gnupg\\openpgp-revocs.d\\DFXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.rev' に保管しました。
    公開鍵と秘密鍵を作成し、署名しました。

    pub   nistp521 2024-08-23 [C]
        A4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    uid                      naa0yama <[email protected]>

副鍵を作成

副鍵の作成前に KEYID を確認しておく 77CXXXXXXXXXXXXX が KEYID です。 よく使うので $env:KEYID="77CXXXXXXXXXXXXX" として変数設定する

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
> gpg --list-secret-keys --keyid-format=long
gpg: 信用データベースの検査
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: 深さ: 0  有効性:   1  署名:   0  信用: 0-, 0q, 0n, 0m, 0f, 1u
[keyboxd]
---------
sec   nistp521/77CXXXXXXXXXXXXX 2024-08-23 [C]
      A4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
uid                 [  究極  ] naa0yama <id@exsample.com>

> $env:KEYID="77CXXXXXXXXXXXXX"

暗号化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
+   > gpg --expert --edit-key $env:KEYID
    gpg (GnuPG) 2.4.5; Copyright (C) 2024 g10 Code GmbH
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.

    秘密鍵が利用できます。

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 究極        有効性: 究極
    [  不明  ] (1). naa0yama <[email protected]>

+   gpg> addkey
    ご希望の鍵の種類を選択してください:
    (3) DSA (署名のみ)
    (4) RSA (署名のみ)
    (5) Elgamal (暗号化のみ)
    (6) RSA (暗号化のみ)
    (7) DSA (機能をあなた自身で設定)
    (8) RSA (機能をあなた自身で設定)
    (10) ECC (署名のみ)
    (11) ECC (機能をあなた自身で設定)
    (12) ECC (暗号化のみ)
    (13) 既存の鍵
    (14) カードに存在する鍵
+   あなたの選択は? 12
    ご希望の楕円曲線を選択してください:
    (1) Curve 25519 *デフォルト
    (2) Curve 448
    (3) NIST P-256
    (4) NIST P-384
    (5) NIST P-521
    (6) Brainpool P-256
    (7) Brainpool P-384
    (8) Brainpool P-512
    (9) secp256k1
+   あなたの選択は? 1
    鍵の有効期限を指定してください。
            0 = 鍵は無期限
        <n>  = 鍵は n 日間で期限切れ
        <n>w = 鍵は n 週間で期限切れ
        <n>m = 鍵は n か月間で期限切れ
        <n>y = 鍵は n 年間で期限切れ
+   鍵の有効期間は? (0)0
    鍵は無期限です
+   これで正しいですか? (y/N) y
+   本当に作成しますか? (y/N) y
    たくさんのランダム・バイトの生成が必要です。キーボードを打つ、マウスを動か
    す、ディスクにアクセスするなどの他の操作を素数生成の間に行うことで、乱数生
    成器に十分なエントロピーを供給する機会を与えることができます。

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 究極        有効性: 究極
    ssb  cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
    [  不明  ] (1). naa0yama <[email protected]>

+   gpg> q
+   変更を保存しますか? (y/N) y

署名

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
+   > gpg --expert --edit-key $env:KEYID

+   gpg> addkey
    ご希望の鍵の種類を選択してください:
    (3) DSA (署名のみ)
    (4) RSA (署名のみ)
    (5) Elgamal (暗号化のみ)
    (6) RSA (暗号化のみ)
    (7) DSA (機能をあなた自身で設定)
    (8) RSA (機能をあなた自身で設定)
    (10) ECC (署名のみ)
    (11) ECC (機能をあなた自身で設定)
    (12) ECC (暗号化のみ)
    (13) 既存の鍵
    (14) カードに存在する鍵
+   あなたの選択は? 10
    ご希望の楕円曲線を選択してください:
    (1) Curve 25519 *デフォルト
    (2) Curve 448
    (3) NIST P-256
    (4) NIST P-384
    (5) NIST P-521
    (6) Brainpool P-256
    (7) Brainpool P-384
    (8) Brainpool P-512
    (9) secp256k1
+   あなたの選択は? 1
    鍵の有効期限を指定してください。
            0 = 鍵は無期限
        <n>  = 鍵は n 日間で期限切れ
        <n>w = 鍵は n 週間で期限切れ
        <n>m = 鍵は n か月間で期限切れ
        <n>y = 鍵は n 年間で期限切れ
+   鍵の有効期間は? (0)0
    鍵は無期限です
+   これで正しいですか? (y/N) y
+   本当に作成しますか? (y/N) y
    たくさんのランダム・バイトの生成が必要です。キーボードを打つ、マウスを動か
    す、ディスクにアクセスするなどの他の操作を素数生成の間に行うことで、乱数生
    成器に十分なエントロピーを供給する機会を与えることができます。

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 究極        有効性: 究極
    ssb  cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
    ssb  ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
    [  不明  ] (1). naa0yama <[email protected]>

+   gpg> q
+   変更を保存しますか? (y/N) y

認証

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
+   > gpg --expert --edit-key $env:KEYID

+   gpg> addkey
    ご希望の鍵の種類を選択してください:
    (3) DSA (署名のみ)
    (4) RSA (署名のみ)
    (5) Elgamal (暗号化のみ)
    (6) RSA (暗号化のみ)
    (7) DSA (機能をあなた自身で設定)
    (8) RSA (機能をあなた自身で設定)
    (10) ECC (署名のみ)
    (11) ECC (機能をあなた自身で設定)
    (12) ECC (暗号化のみ)
    (13) 既存の鍵
    (14) カードに存在する鍵
+   あなたの選択は? 11

    このECC鍵にありうる操作: Sign Authenticate
    現在の認められた操作: Sign

    (S) 署名機能を反転する
    (A) 認証機能を反転する
    (Q) 完了

+   あなたの選択は? S # 署名機能 を削除

    このECC鍵にありうる操作: Sign Authenticate
    現在の認められた操作:

    (S) 署名機能を反転する
    (A) 認証機能を反転する
    (Q) 完了

+   あなたの選択は? A # 認証機能 を付加

    このECC鍵にありうる操作: Sign Authenticate
    現在の認められた操作: Authenticate

    (S) 署名機能を反転する
    (A) 認証機能を反転する
    (Q) 完了

+   あなたの選択は? q
    ご希望の楕円曲線を選択してください:
    (1) Curve 25519 *デフォルト
    (2) Curve 448
    (3) NIST P-256
    (4) NIST P-384
    (5) NIST P-521
    (6) Brainpool P-256
    (7) Brainpool P-384
    (8) Brainpool P-512
    (9) secp256k1
+   あなたの選択は? 1
    鍵の有効期限を指定してください。
            0 = 鍵は無期限
        <n>  = 鍵は n 日間で期限切れ
        <n>w = 鍵は n 週間で期限切れ
        <n>m = 鍵は n か月間で期限切れ
        <n>y = 鍵は n 年間で期限切れ
+   鍵の有効期間は? (0)0
    鍵は無期限です
+   これで正しいですか? (y/N) y
+   本当に作成しますか? (y/N) y
    たくさんのランダム・バイトの生成が必要です。キーボードを打つ、マウスを動か
    す、ディスクにアクセスするなどの他の操作を素数生成の間に行うことで、乱数生
    成器に十分なエントロピーを供給する機会を与えることができます。

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 究極        有効性: 究極
    ssb  cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
    ssb  ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
    ssb  ed25519/77AXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: A
    [  不明  ] (1). naa0yama <[email protected]>

+   gpg> q
+   変更を保存しますか? (y/N) y

Keybase の不具合対応

Keybase は GnuPG 2.4 以上で鍵を作成すると Keybase が対応していない形式(AEAD)が自動で追加されるため鍵をアップロード出来ない状態になる。 筆者もハマり散らかし大変困ったので、ワークアラウンド(暫定対処)を記載しておく。

対処しないとこのようなエラーとなり登録出来ない

- ERROR key generation error: Unknown signature subpacket: 34 (error 905)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
+   > gpg -k
    C:\Users\naa0yama\AppData\Roaming\gnupg\pubring.kbx
    ---------------------------------------------------
    pub   nistp521 2024-09-13 [C]
          A4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    uid           [  究極  ] naa0yama <[email protected]>
    sub   cv25519 2024-09-13 [E]
    sub   ed25519 2024-09-13 [S]
    sub   ed25519 2024-09-13 [A]

+   > keybase pgp select
    You are selecting a PGP key from your local GnuPG keychain, and
    will publish a statement signed with this key to make it part of
    your Keybase.io identity.

    Note that GnuPG will prompt you to perform this signature.

    You can also import the secret key to *local*, *encrypted* Keybase
    keyring, enabling decryption and signing with the Keybase client.
    To do that, use "--import" flag.

    Learn more: keybase pgp help select

    #    Algo   Key Id             Created   UserId
    =    ====   ======             =======   ======
    1    521E   77CXXXXXXXXXXXXX             naa0yama <[email protected]>
+   Choose a key: 1
-   - ERROR key generation error: Unknown signature subpacket: 34 (error 905)

対応としては下記で対処できる AEAD: OCB の箇所が、 AEAD: となれば対処出来ている

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
+   > gpg --expert --edit-key $env:KEYID
    gpg (GnuPG) 2.4.5; Copyright (C) 2024 g10 Code GmbH
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.

    秘密鍵が利用できます。

        pub  nistp521/77CXXXXXXXXXXXXX
            作成: 2024-08-24  有効期限: 無期限      利用法: C
            信用: 究極        有効性: 究極
        ssb  cv25519/77EXXXXXXXXXXXXX
            作成: 2024-08-24  有効期限: 無期限      利用法: E
        ssb  ed25519/77SXXXXXXXXXXXXX
            作成: 2024-08-24  有効期限: 無期限      利用法: S
        ssb  ed25519/77AXXXXXXXXXXXXX
            作成: 2024-08-24  有効期限: 無期限      利用法: A
        [  不明  ] (1). naa0yama <[email protected]>

+   gpg> showpref
    [  究極  ] (1). naa0yama <[email protected]>
        暗号方式: AES256, AES192, AES, 3DES
+       AEAD: OCB
        ダイジェスト: SHA512, SHA384, SHA256, SHA224, SHA1
        圧縮: ZLIB, BZIP2, ZIP, 無圧縮
        機能: MDC, AEAD, 鍵サーバ 修正しない

+   gpg> setpref AES256 AES192 AES 3DES SHA512 SHA384 SHA256 SHA224 SHA1 ZLIB BZIP2 ZIP Uncompressed mdc no-ks-modify
    優先指定の一覧を設定:
        暗号方式: AES256, AES192, AES, 3DES
-       AEAD:
        ダイジェスト: SHA512, SHA384, SHA256, SHA224, SHA1
        圧縮: ZLIB, BZIP2, ZIP, 無圧縮
        機能: MDC, 鍵サーバ 修正しない
+   優先指定を本当に更新しますか? (y/N) y
+   gpg> save

バックアップ

エクスポート用に USBドライブを用意し F: にマウントします。 この状態でエクスポート、ディレクトリーを作成し移動しておきます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
> gpg --list-secret-keys --keyid-format=long
gpg: 信用データベースの検査
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: 深さ: 0  有効性:   1  署名:   0  信用: 0-, 0q, 0n, 0m, 0f, 1u
[keyboxd]
---------
sec   nistp521/77CXXXXXXXXXXXXX 2024-08-23 [C]
      A4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
uid                 [  究極  ] naa0yama <id@exsample.com>

> $env:KEYID="77CXXXXXXXXXXXXX"

> New-Item "$env:GNUPGHOME\Export" -ItemType Directory
> Set-Location -Path "$env:GNUPGHOME\Export"

主鍵・副鍵秘密鍵

1
> gpg --armor --output master-and-sub.key --export-secret-keys $env:KEYID

主鍵公開鍵

1
> gpg --armor --output master-public.asc --export $env:KEYID

主鍵失効証明書

--generate-revocation <user-id> である必要があるようなので注意

1
> gpg --output master-revoke.asc --generate-revocation "naa0yama"

副鍵のみの秘密鍵

1
> gpg --armor --output sub.key --export-secret-subkeys $env:KEYID

エクスポートしたファイルを確認しておきます。 4つのファイルがあるはずです。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
> ls

    Directory: F:\gnupg\Export

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2024/09/13    12:46           2347 master-and-sub.key
-a---          2024/09/13    12:46           1837 master-public.asc
-a---          2024/09/13    12:47            386 master-revoke.asc
-a---          2024/09/13    12:48           2193 sub.key

ZIP で圧縮して保管しておきます。 そうしておくことで、ディレクトリー内のファイル変更してもあとから確認できるのでそうします

1
2
3
4
> $filename = Get-Date -Format "yyyyMMddTHHmmss"
> Compress-Archive `
  -Path "$env:GNUPGHOME" `
  -DestinationPath "F:\gnupg_$filename"

YubiKey

GPG Key の初期化

Windows Terminal で別タブを開き GNUPGHOME を変更して新しいデーターベースとして作業する。 また、作業前に2つの物理デバイスに先ほどまで利用していた F:\gnupg 内をコピーして1つは物理的に取り外して作業することを推奨する。

Important
必ず、2つの物理デバイスにバックアップを取り一つはデバイスを取り外してから作業してください。
大事なので2回言います(1敗)

GPG Key の利用は初めてなので初期化しておく

1
2
3
4
> New-Item "C:\temp\gpg2" -ItemType Directory

> $env:GNUPGHOME="C:\temp\gpg2"
> Set-Location -Path $env:GNUPGHOME
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
    > gpg --version
    gpg (GnuPG) 2.4.5
    libgcrypt 1.10.3
    Copyright (C) 2024 g10 Code GmbH
    License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.

-   Home: C:\Users\naa0yama\AppData\Roaming\gnupg
+   Home: C:\temp\gpg2
    サポートしているアルゴリズム:
    公開鍵: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
    暗号方式: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256,
        TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256
    ハッシュ: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
    圧縮: 無圧縮, ZIP, ZLIB, BZIP2

副鍵の秘密鍵のみ Import

先ほど F:\Export\sub.key に保存した副鍵の秘密鍵のみをインポートするが GPG データストアが初期化されていることを確認しておく gpg -K でなにも表示されなければ問題ない。

1
> gpg -K

副鍵を Import する

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
> gpg --import F:\gnupg\Export\sub.key
gpg: 鍵7EXXXXXXXXXXXXXX: 公開鍵"naa0yama <[email protected]>"をインポートしました
gpg: 'secring.gpg'の移行にはスマードカードそれぞれで以下を実行してください: gpg --card-status
gpg: 鍵7EXXXXXXXXXXXXXX: 秘密鍵をインポートしました
gpg:           処理数の合計: 1
gpg:             インポート: 1
gpg:       秘密鍵の読み込み: 1
gpg:     秘密鍵のインポート: 1

> gpg --list-key
C:\temp\gpg2\pubring.kbx
------------------------
pub   nistp521 2024-08-24 [C]
      A4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
uid           [  不明  ] naa0yama <id@exsample.com>
sub   cv25519 2024-08-24 [E]
sub   ed25519 2024-08-24 [S]
sub   ed25519 2024-08-24 [A]

Import が完了時点では信頼がないため [ 不明 ] となっている。そのため、信用設定をする。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
+   > gpg --edit-key "naa0yama"
    gpg (GnuPG) 2.4.5; Copyright (C) 2024 g10 Code GmbH
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.

    秘密副鍵が利用できます。

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 不明の     有効性: 不明の
    ssb  cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
    ssb  ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
    ssb  ed25519/77AXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: A
    [  不明  ] (1). naa0yama <[email protected]>

+   gpg> trust
    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 不明の     有効性: 不明の
    ssb  cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
    ssb  ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
    ssb  ed25519/77AXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: A
    [  不明  ] (1). naa0yama <[email protected]>

    他のユーザの鍵を正しく検証するために、このユーザの信用度を決めてください
    (パスポートを見せてもらったり、他から得たフィンガープリントを検査したり、などなど)

    1 = 知らない、または何とも言えない
    2 = 信用し ない
    3 = まぁまぁ信用する
    4 = 充分に信用する
    5 = 究極的に信用する
    m = メーン・メニューに戻る

+   あなたの決定は? 5
+   本当にこの鍵を究極的に信用しますか? (y/N) y

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 不明の     有効性: 不明の
    ssb  cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
    ssb  ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
    ssb  ed25519/77AXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: A
    [  不明  ] (1). naa0yama <[email protected]>
    プログラムを再起動するまで、表示された鍵の有効性は正しくないかもしれない、
    ということを念頭においてください。

+   gpg> q

下記を確認しておく

  • A4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX の鍵が主鍵のため pub になっていること sec の場合は秘密鍵を含んでしまっているため GPG Key の初期化からやり直し
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
> gpg --list-key
gpg: 信用データベースの検査
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: 深さ: 0  有効性:   1  署名:   0  信用: 0-, 0q, 0n, 0m, 0f, 1u
C:\temp\gpg2\pubring.kbx
------------------------
pub   nistp521 2024-08-24 [C]
      A4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
uid           [  究極  ] naa0yama <id@exsample.com>
sub   cv25519 2024-08-24 [E]
sub   ed25519 2024-08-24 [S]
sub   ed25519 2024-08-24 [A]

YubiKey の OpenPGP を初期化

1
2
3
4
5
6
7
> ykman openpgp reset
WARNING! This will delete all stored OpenPGP keys and data and restore factory settings. Proceed? [y/N]: y
Resetting OpenPGP data, don't remove the YubiKey...
Reset complete. OpenPGP data has been cleared and default PINs are set.
PIN:         123456
Reset code:  NOT SET
Admin PIN:   12345678

KDF の有効化

YubiKey 5 を使うので KDF(Key Derived Format) が 5.2.3 以上なら設定できる。 (YubiKey は ファームウェアアップデートは自身で出来ないので足りてなければ、新しいの買うしか無い)

Gpg4win をインストールすると PowerShell で gpg コマンドが使えるので Windows 11 で作業した。

Topic
最初にやらないと、リセットしないと変更出来なくなる
1
2
3
4
> gpg --edit-card

gpg/card> admin
gpg/card> kdf-setup

デフォルトの PIN が下記であった

1
2
PIN:       123456
Admin PIN: 12345678

完了すると下記のようになる on になれば問題なし

1
2
3
4
gpg/card> list

- KDF setting ......: off
+ KDF setting ......: on

PIN, Admin PIN の設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
+   gpg/card> passwd
    gpg: OpenPGPカードno. DXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX を検出

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

+   あなたの選択は? 1
    PIN changed.

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

+   あなたの選択は? 3
    PIN changed.

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

+   あなたの選択は? q

その他の設定

ロマンなので、設定する

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
gpg/card> name
カード所有者の姓 (surname): Naoki
カード所有者の名 (given name): Aoyama

gpg/card> login
ログインデータ (アカウント名): naa0yama

gpg/card> lang
言語の優先指定: ja

gpg/card> salutation
敬称 (M = Mr., F = Ms., あるいは空白): M

gpg/card> list

Name of cardholder: Aoyama Naoki
Language prefs ...: ja
Salutation .......: Mr.
Login data .......: naa0yama

PINの入力をキャッシュしないようにする

gpg-agent を常駐しておくので、 YubiKey でキャッシュはしないように設定してしまう。 デフォルトでは抜き差ししたり、再起動するまで PIN 入力の必要がない。

1
gpg/card> forcesig

PINの試行回数の設定

ykman で PIN の試行回数を変更する

RESET-CODE-RETRIES はすべての情報がリセットされるため、リトライ条件を設定しないことにした。ので 99 としている

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
> ykman openpgp access
set-retries           set the number of retry attempts for the User PIN, Reset Code, and Admin PIN

> ykman openpgp access set-retries -h
Usage: ykman.exe openpgp access set-retries [OPTIONS] PIN-RETRIES RESET-CODE-RETRIES ADMIN-PIN-RETRIES

> ykman openpgp access set-retries 5 99 10
Enter Admin PIN:
Set PIN retry counters to: 5 99 10? [y/N]: y
Number of PIN/Reset Code/Admin PIN retries set.

タッチポリシーの設定

YubiKey の 真ん中のボタンはタッチセンサーになっている。 そのため、鍵使用時にタッチするようにすれば物理的にタッチしなければ承認されないためセキュリティが強固になる。デフォルトの設定はタッチは必要ない

  • KEY のそれぞれは
    • SIG 署名(Sign)
    • DEC 暗号化(Encrypt)
    • AUT 認証(Authenticate)
    • ATT 証明(Certify)
  • Touch policies
    • On タッチ必須にする
    • Cached に設定すれば、15秒タッチがキャッシュされる
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
> ykman openpgp keys set-touch -h
Usage: ykman.exe openpgp keys set-touch [OPTIONS] KEY POLICY

  Set the touch policy for OpenPGP keys.

  The touch policy is used to require user interaction for all operations using the private key on the YubiKey. The
  touch policy is set individually for each key slot. To see the current touch policy, run the "openpgp info"
  subcommand.

  Touch policies:

  Off (default)   no touch required
  On              touch required
  Fixed           touch required, can't be disabled without deleting the private key
  Cached          touch required, cached for 15s after use
  Cached-Fixed    touch required, cached for 15s after use, can't be disabled
                  without deleting the private key

  KEY     key slot to set (sig, dec, aut or att)
  POLICY  touch policy to set (on, off, fixed, cached or cached-fixed)
  
> ykman openpgp keys set-touch
Usage: ykman.exe openpgp keys set-touch [OPTIONS] KEY POLICY
Try 'ykman.exe openpgp keys set-touch -h' for help.

Error: Missing argument 'KEY'. Choose from:
        SIG,
        DEC,
        AUT,
        ATT

とりあえず、鍵を直接利用することは少ないためすべてタッチ必須とした

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
> ykman openpgp keys set-touch sig On
> ykman openpgp keys set-touch dec On
> ykman openpgp keys set-touch aut Off
> ykman openpgp keys set-touch att On

> ykman openpgp info
OpenPGP version:            3.4
Application version:        5.2.4
PIN tries remaining:        5
Reset code tries remaining: 99
Admin PIN tries remaining:  10
Require PIN for signature:  Always
KDF enabled:                True
Touch policies:
  Signature key:      On
  Encryption key:     On
  Authentication key: Off
  Attestation key:    On

鍵の転送

YubiKey に鍵を転送する。 このとき作業ディレクトリーに存在する鍵は転送が完了すると自動的にさ削除されるため一時ディレクトリーを掘って gpg --import でクリーンな完了を作っている

Topic
YubiKey に転送が完了すると C:\temp\gpg2 から鍵は最後の save を実行すると削除されます。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
> gpg --list-secret-keys --keyid-format=long
gpg: 信用データベースの検査
gpg: marginals needed: 3  completes needed: 1  trust model: pgp
gpg: 深さ: 0  有効性:   1  署名:   0  信用: 0-, 0q, 0n, 0m, 0f, 1u
[keyboxd]
---------
sec   nistp521/77CXXXXXXXXXXXXX 2024-08-23 [C]
      A4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
uid                 [  究極  ] naa0yama <id@exsample.com>

> $env:KEYID="77CXXXXXXXXXXXXX"

> gpg --edit-key $env:KEYID
gpg (GnuPG) 2.4.5; Copyright (C) 2024 g10 Code GmbH
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

秘密副鍵が利用できます

pub  nistp521/77CXXXXXXXXXXXXX
     作成: 2024-08-24  有効期限: 無期限      利用法: C
     信用: 究極        有効性: 究極
ssb  cv25519/77EXXXXXXXXXXXXX
     作成: 2024-08-24  有効期限: 無期限      利用法: E
ssb  ed25519/77SXXXXXXXXXXXXX
     作成: 2024-08-24  有効期限: 無期限      利用法: S
ssb  ed25519/77AXXXXXXXXXXXXX
     作成: 2024-08-24  有効期限: 無期限      利用法: A
[  不明  ] (1). naa0yama <id@exsample.com>

暗号化

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
+   gpg> key 1

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 究極        有効性: 究極
+   ssb* cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
    ssb  ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
    ssb  ed25519/77AXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: A
    [  不明  ] (1). naa0yama <[email protected]>

+   gpg> keytocard
    鍵を保管する場所を選択してください:
    (2) 暗号化鍵
+   あなたの選択は? 2

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 究極        有効性: 究極
    ssb* cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
    ssb  ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
    ssb  ed25519/77AXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: A
    [  不明  ] (1). naa0yama <[email protected]>

    注意: 秘密鍵のローカルなコピーは"save"だけで削除されます。
+   gpg> key 1

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 究極        有効性: 究極
-   ssb  cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
    ssb  ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
    ssb  ed25519/77AXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: A
    [  不明  ] (1). naa0yama <[email protected]>

署名

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
+   gpg> key 2

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 究極        有効性: 究極
    ssb  cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
+   ssb* ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
    ssb  ed25519/77AXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: A
    [  不明  ] (1). naa0yama <[email protected]>

+   gpg> keytocard
    鍵を保管する場所を選択してください:
    (1) 署名鍵
    (3) 認証鍵
+   あなたの選択は? 1

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 究極        有効性: 究極
    ssb  cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
    ssb* ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
    ssb  ed25519/77AXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: A
    [  不明  ] (1). naa0yama <[email protected]>

    注意: 秘密鍵のローカルなコピーは"save"だけで削除されます。
+   gpg> key 2

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 究極        有効性: 究極
    ssb  cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
-   ssb  ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
    ssb  ed25519/77AXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: A
    [  不明  ] (1). naa0yama <[email protected]>

認証

YubiKey の鍵スロットが各用途 1つ しかないため RSA 2048 の鍵は後ほど PIV カードのほうに登録するため Key 3 のみ転送する

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
+   gpg> key 3

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 究極        有効性: 究極
    ssb  cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
+   ssb ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
    ssb* ed25519/77AXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: A
    [  不明  ] (1). naa0yama <[email protected]>

+   gpg> keytocard
    鍵を保管する場所を選択してください:
    (3) 認証鍵
+   あなたの選択は? 1

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 究極        有効性: 究極
    ssb  cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
    ssb  ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
    ssb* ed25519/77AXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: A
    [  不明  ] (1). naa0yama <[email protected]>

    注意: 秘密鍵のローカルなコピーは"save"だけで削除されます。
+   gpg> key 3

    pub  nistp521/77CXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: C
        信用: 究極        有効性: 究極
    ssb  cv25519/77EXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: E
    ssb  ed25519/77SXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: S
-   ssb  ed25519/77AXXXXXXXXXXXXX
        作成: 2024-08-24  有効期限: 無期限      利用法: A
    [  不明  ] (1). naa0yama <[email protected]>

認証鍵 RSA

鍵を証明書に変換

前述した通り、 YubiKey には各用途ごとに1つしかスロットがないため、 Ed25519 と RSA 2048 の鍵を登録は出来なかった。物理機器として Ed25519 に対応してない機器が少なからずあるため、 RSA 2048 の鍵も用意しておきたい。

そのため調査した所、本記事で書いている Gpg4win (ver 4.3.1) のバージョンに添付されている gpg-agent では PIV 証明書を読むこともでき、簡易的に ssh-add -l で確認したところ読み込めるようなのでこちらに設定する。

GPG の副鍵を OpenSSL 形式に変換して PIV に転送することを考えていたが、調査の結果 “技術的には可能(不可能)” とわかったので大人しく新しい鍵を生成して PIV に登録する。 このさい、 YubiKey PIV Manager を使わないのはスペアキーを作るために YubiKey 外で作成する必要があるためです。また、今回は以前利用していた RSA 鍵を証明書に変換して登録してみる。 鍵を使い回すことで若干のリスクではあるがすべてのPC上鍵の生置きを解消できることと既存の鍵が YubiKey に1つ入っていれば移行簡単なためこの方法とした。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# ディレクトリ移動
> Set-Location -Path $env:GNUPGHOME

# OpenSSL-Win64 path 通し
Set-Item Env:Path $Env:Path";C:\Program Files\OpenSSL-Win64\bin"

# CN を変数化
$OPENSSL_CN = "naa0yama"

# ssh-key を生成 RSA 2048
> ssh-keygen -t rsa -b 2048 -m PEM -f tmpRSA

# cert config を作成
# デジタル認証とクライアント認証に機能を絞る
> $confContent = @"
distinguished_name=none
x509_extensions = usr_cert

[usr_cert]
keyUsage=digitalSignature
extendedKeyUsage = clientAuth

[none]
"@

> Set-Content -Path tmp.conf -Value $confContent

> $env:OPENSSL_CONF="tmp.conf"
> openssl req -key ./tmpRSA -days 7000 -x509 -subj /CN=$OPENSSL_CN > out.cer
> openssl pkcs12 -export -in out.cer -inkey ./tmpRSA -name $OPENSSL_CN > out.p12

YubiKey PIV の準備

PIN, PUK のリトライは3回となっていて、少し厳しいため緩和する

Topic
set-retries を先に設定しなければ、 PIN, PUK がリセットされるので先にする。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
> ykman piv reset
WARNING! This will delete all stored PIV data and restore factory settings. Proceed? [y/N]: y
Resetting PIV data...
Reset complete. All PIV data has been cleared from the YubiKey.
Your YubiKey now has the default PIN, PUK and Management Key:
        PIN:    123456
        PUK:    12345678
        Management Key: 010203040506070801020304050607080102030405060708

> ykman piv access set-retries 5 10

PIV 機能を初期化し PIN, PUK, Management Key を設定する

1
2
3
4
        
> ykman piv access change-pin
> ykman piv access change-puk
> ykman piv access change-management-key --generate

証明書をスロット 9a , 9e に投入する

1
2
3
4
5
> ykman piv certificates import 9a .\out.p12
> ykman piv keys         import 9a .\out.p12

> ykman piv certificates import 9e .\out.p12
> ykman piv keys         import 9e .\out.p12
Topic
PIV version 5.4.3 以下では ykman piv info では Private key type: EMPTY と表示される状態を確認しています。うまく設定が出来たか確認出来ない場合は YubiKey を刺し直し、 ssh-add -l などで 2つ鍵が見えることを確認してください。この場合は 9A の鍵のみ表示されるため 2つとなります。

秘密鍵と公開鍵がはいったことを確認しておくとよい

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  > ykman piv info
  PIV version:              5.4.3
  PIN tries remaining:      5/5
  PUK tries remaining:      10/10
  Management key algorithm: TDES
  CHUID: ....
  CCC:   No data available
  Slot 9A (AUTHENTICATION):
+   Private key type: RSA2048
+   Public key type:  RSA2048
+   Subject DN:       [email protected]
    Issuer DN:        [email protected]
    Serial:           XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
    Fingerprint:      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    Not before:       2024-08-26T04:16:54+00:00
    Not after:        2043-10-26T04:16:54+00:00

  Slot 9E (CARD_AUTH):
+   Private key type: RSA2048
+   Public key type:  RSA2048
+   Subject DN:       [email protected]
    Issuer DN:        [email protected]
    Serial:           XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX:XX
    Fingerprint:      XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    Not before:       2024-08-26T04:16:54+00:00
    Not after:        2043-10-26T04:16:54+00:00

YubiKey の設定を確認

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
> gpg --edit-card

Reader ...........: Yubico YubiKey OTP FIDO CCID 0
Application ID ...: D27XXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Application type .: OpenPGP
Version ..........: 3.4
Manufacturer .....: Yubico
Serial number ....: XXXXXXXX
Name of cardholder: naa0yama
Language prefs ...: ja
Salutation .......: Mr.
URL of public key : https://keybase.io/naa0yama/pgp_keys.asc
Login data .......: naa0yama
Signature PIN ....: 強制
Key attributes ...: ed25519 cv25519 ed25519
Max. PIN lengths .: 127 127 127
PIN retry counter : 5 99 10
Signature counter : 0
KDF setting ......: on
UIF setting ......: Sign=on Decrypt=on Auth=on
Signature key ....: XXXX XXXX XXXX XXXX XXXA  XXXX XXXX XXXX XXXX XXXX
      created ....: 2024-09-13 03:43:22
Encryption key....: XXXX XXXX XXXX XXXX XXXA  XXXX XXXX XXXX XXXX XXXX
      created ....: 2024-09-13 03:14:12
Authentication key: XXXX XXXX XXXX XXXX XXXA  XXXX XXXX XXXX XXXX XXXX
      created ....: 2024-09-13 03:44:07
General key info..:
sub  ed25519/77CXXXXXXXXXXXXX 2024-09-13 naa0yama <id@exsample.com>
sec   nistp521/77CXXXXXXXXXXXXX  作成: 2024-09-13  有効期限: 無期限
ssb   cv25519/77SXXXXXXXXXXXXX  作成: 2024-09-13  有効期限: 無期限
ssb   ed25519/77CXXXXXXXXXXXXX  作成: 2024-09-13  有効期限: 無期限
ssb   ed25519/77AXXXXXXXXXXXXX  作成: 2024-09-13  有効期限: 無期限

> ykman openpgp info
OpenPGP version:            3.4
Application version:        5.2.4
PIN tries remaining:        5
Reset code tries remaining: 99
Admin PIN tries remaining:  10
Require PIN for signature:  Always
KDF enabled:                True
Touch policies:
  Signature key:      On
  Encryption key:     On
  Authentication key: Off
  Attestation key:    On

クリーンアップ

GPG Keys を手元の PC から抹消します。 ここでの範囲は下記で抹消する場合は十分にきおつけてください。

1
2
3
cd
Remove-Item -Recurse -Force -Verbose "F:\gnupg\"
Remove-Item -Recurse -Force -Verbose "C:\temp\gpg2"

公開鍵鯖へ Upload

Keybase

keybase は E2EE(End To End Encrypt)で Chat、チームChat、ファイル共有、公開鍵管理、暗号化 Git レポジトリー、デバイス管理が利用できる。ファイル共有は無料プランでも 250GB あるそうです。

Warning
iOS/Android からアカウント作成すると自身の GPG Key を登録出来なかったため、 PCから作成することをおすすめする。 iOS/Android から作成してしまった場合はアカウントをリフレッシュすることでできるようになるが、申告から7日後でなければ対応出来ないため注意
Note

Keybase に登録する Windows Client は 本記事で多用している $env:GNUPGHOME 変数に対応していない。 そのため、一時的に Windows 標準の場所に GPG を展開し登録する必要がある。

通常であれば %APPDATA%\gnupg になります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
+   > gpg --version
    gpg (GnuPG) 2.4.5
    libgcrypt 1.10.3
    Copyright (C) 2024 g10 Code GmbH
    License GNU GPL-3.0-or-later <https://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.

+   Home: C:\Users\naa0yama\AppData\Roaming\gnupg
    サポートしているアルゴリズム:
    公開鍵: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
    暗号方式: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256,
          TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256
    ハッシュ: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
    圧縮: 無圧縮, ZIP, ZLIB, BZIP2

F:\gnupg はUSBデバイスに保管しているためそこからコピーして配置しています

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
+   > Copy-Item -Path F:\gnupg -Destination $env:APPDATA -Recurse

+   > gpg -k
    C:\Users\naa0yama\AppData\Roaming\gnupg\pubring.kbx
    ---------------------------------------------------
    pub   nistp521 2024-08-24 [C]
          A4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
    uid           [  究極  ] naa0yama <[email protected]>
    sub   cv25519 2024-08-24 [E]
    sub   ed25519 2024-08-24 [S]
    sub   ed25519 2024-08-24 [A]

+   > keybase pgp select
    You are selecting a PGP key from your local GnuPG keychain, and
    will publish a statement signed with this key to make it part of
    your Keybase.io identity.

    Note that GnuPG will prompt you to perform this signature.

    You can also import the secret key to *local*, *encrypted* Keybase
    keyring, enabling decryption and signing with the Keybase client.
    To do that, use "--import" flag.

    Learn more: keybase pgp help select

    #    Algo   Key Id             Created   UserId
    =    ====   ======             =======   ======
    1    521E   77CXXXXXXXXXXXXX             naa0yama <[email protected]>
    Choose a key: 1
    - INFO Generated new PGP key:
    - INFO   user: naa0yama <[email protected]>
    - INFO   521-bit ECDSA key, ID 77CXXXXXXXXXXXXX, created 2024-09-13

完了すると、下記のように Keybase App から鍵のフィンガープリントが見えます

keybase は公開鍵を ダウンロードできるためこちらをダウンロードして確認してみましょう。
問題なさそうですね

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
> curl -sL https://keybase.io/naa0yama/pgp_keys.asc | `
  gpg --show-key --with-sig-list
pub   nistp521 2024-09-13 [C]
      65284A0A9205C52EBC16BBCF794676DEF45A4D7F
uid                      Naoki Aoyama <9667078+naa0yama@users.noreply.github.com>
sig 3        794676DEF45A4D7F 2024-09-13  [自己署名]
sub   cv25519 2024-09-13 [E]
sig          794676DEF45A4D7F 2024-09-13  [自己署名]
sub   ed25519 2024-09-13 [S]
sig          794676DEF45A4D7F 2024-09-13  [自己署名]
sub   ed25519 2024-09-13 [A]
sig          794676DEF45A4D7F 2024-09-13  [自己署名]

GitHub

GitHub アカウントに GPG キーを追加する - GitHub Docs

公開鍵のURL設定

YubiKey に公開鍵の公開URLを設定します。

1
2
3
4
5
> gpg --edit-card

gpg/card> admin
gpg/card> url
URL to retrieve public key: https://keybase.io/naa0yama/pgp_keys.asc

使い方

やらなかったこと

wsl2-ssh-pageant, npiperelay は使わない

ssh-agent を WSL2 で利用する場合いくつかの方法があり、よく出てくる BlackReloaded/wsl2-ssh-pageant は現在メンテナンスされていない。作者が Windows PC から卒業されたため現在はアーカイブされている。

jstarks/npiperelay は現在も利用出来ますが、最後のリリースと Commit が 4年前となってい実質開発停止となっている。また Windows の NamedPipe を socat でリレーするという仕組みのため汎用性が高いが Windows に標準登録されている OpenSSH のバージョンが古いためそのままリレーすると不具合が出るようである。

YubiKey PIV でタッチ強制

YubiKey PIV ではデフォルトでタッチは強制されないが、 import 時にタッチを強制または CACHED を設定することも可能。これをすると対応 Slot の鍵を使う場合は YubiKey のタッチを強制できるが画面上には何も出ないためタッチを忘れることが多く、かつ gpg-agent で TTL cache も設定する術がないため毎回聞かれる羽目になったので設定を解除した。

1
ykman piv keys import --touch-policy CACHED SLOT PRIVATE-KEY

gpg-agent の転送

本記事の冒頭でも書いたが Windows の SSH 事情は本当に混沌としていて、今回 GPG を導入したので本来であれば、リモートでも Git Commit に署名をしたかったのだが、、 SSH の事象と同一で Gpg4win 同梱の gpg-agent を利用して RemoteForward で SOCK を繋げ手元に持ってくるつもりだったがまたしても Windows 特有の Unixdomain socket だったため実現出来なかった。

詳細は下記 Issue で議論されている。

私の場合は、常用する GPG 鍵はすべて副鍵であり Yubikey に格納されている鍵になるため紛失以外では失効の要因は無いと思われるので SSH Signing keys で妥協することにした。

FAQ

鍵の編集

鍵を編集する場合は microSD カードを PC に接続し Backup として作成した zip を解答して作業する例えば gnupg_20240829T002740.zip のバックアップを使う場合は下記である。

1
2
3
4
5
6
7
8
9
# 作業用のディレクトリを初期化
> cd
> Remove-Item -Recurse -Force -Verbose "F:\gnupg\"

# バックアップを展開
> Expand-Archive -Path "F:\gnupg_20240829T002740.zip" -DestinationPath "F:\"

> $env:GNUPGHOME="F:\gnupg"
> Set-Location -Path "$env:GNUPGHOME"

この状態で gpg -K を実行するとすべての鍵が読み込まれ、秘密鍵に sec と付くはずである あとは鍵を編集すれば良い

1
2
3
4
5
6
7
8
9
> gpg -K
F:\gnupg\pubring.kbx
--------------------
sec   nistp521 2024-08-28 [C]
      A4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
uid           [  究極  ] naa0yama <id@exsample.com>
ssb   cv25519 2024-08-28 [E]
ssb   ed25519 2024-08-28 [S]
ssb   ed25519 2024-08-28 [A]

編集後は

  • バックアップの作成

  • セカンド microSD への転送

  • 作業端末から削除を忘れずに実施すること

    1
    2
    3
    
    cd
    Remove-Item -Recurse -Force -Verbose "F:\gnupg\"
    Remove-Item -Recurse -Force -Verbose "C:\temp\gpg2"

副鍵の期限を伸ばす場合は公開鍵配布し直し?

GPG Keys の有効期限を今回は副鍵であること、と通常は YubiKey に保管し抜けない(コピーを窃盗出来ない)状態で使うことが前提のため有効期限を設定しなかったが有効期限を設定した場合公開鍵も変更になり各サーバーに再配布する必要があるようだ

環境リセット

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
#
# 管理者権限プロンプトを立ち上げて作業
#

winget uninstall Yubico.Piv-Tool
winget uninstall Yubico.YubiKeyManagerCLI
winget uninstall Yubico.YubiKeyPersonalizationTool
winget uninstall Yubico.YubiKeySmartCardMinidriver
winget uninstall Yubico.YubikeyManager
winget uninstall GnuPG.Gpg4win
winget uninstall NathanBeals.WinSSH-Pageant

Remove-Item -Recurse -Force -Verbose $env:USERPROFILE\AppData\Local\gnupg
Remove-Item -Recurse -Force -Verbose $env:USERPROFILE\AppData\Local\Yubico
Remove-Item -Recurse -Force -Verbose $env:USERPROFILE\AppData\Roaming\kleopatra
Remove-Item -Recurse -Force -Verbose $env:USERPROFILE\AppData\Roaming\gnupg

復元

1
2
3
4
5
6
#
# 管理者権限プロンプトを立ち上げて作業
#

winget install GnuPG.Gpg4win
winget install Yubico.YubiKeyManagerCLI

設定の方は gpg-agent.conf と scdaemon.conf の設定が必要です

ファクトリーリセット

gpg コマンドで実施できるが、 yubico のドキュメントでは、 ykman openpgp reset を使えと書いてあるのでそっちでリセットが推奨のようだ

https://support.yubico.com/hc/en-us/articles/360013761339-Resetting-the-OpenPGP-Application-on-the-YubiKey

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# OpenPGP の初期化
> ykman openpgp reset
WARNING! This will delete all stored OpenPGP keys and data and restore factory settings. Proceed? [y/N]: y
Resetting OpenPGP data, don't remove the YubiKey...
Reset complete. OpenPGP data has been cleared and default PINs are set.
PIN:         123456
Reset code:  NOT SET
Admin PIN:   12345678

# PIV の初期化
> ykman piv reset

VSCode で AgentForward が効かない

Windows で .ssh/config に下記を記載しておく

.ssh/config
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Host naaoyama-01
  User                 naa0yama
  Hostname             192.0.2.1
  Port                 22
  ForwardAgent         yes
  ControlMaster        no
  ExitOnForwardFailure Yes

Host *
  ServerAliveInterval 5s
  ServerAliveCountMax 300

この状態で VSCode 上で Terminal を開き ssh-add -l すると下記のエラーとなり SSH Forwarding 出来てなかった

1
2
$ ssh-add -L
Error connecting to agent: No such file or directory

GitHub で Issue が上がってましたのでこれを利用します。

うまく設定されていない場合は oneline を実行すると解消する 自分はスクリプトにしておいた

1
export SSH_AUTH_SOCK=$(ls -t /tmp/ssh-**/* | head -1)

更に読み進めると settings.json に下記を設定すると解消するらしい terminal.integrated.persistentSessionReviveProcess, terminal.integrated.enablePersistentSessions を設定することで ターミナルの状態を復元するため不具合が発生するらしい。

1
2
3
4
5
6
7
8
9
{
  // ssh-agent を WSL2 や devcontainer で使うための回避策
  "remote.SSH.enableAgentForwarding": true,
  "remote.SSH.useLocalServer": false,                             // Window 間で別々の接続にする
  "remote.SSH.useExecServer": false,                              // 従来の接続方式を利用する
  "remote.SSH.remoteServerListenOnSocket": true,                  // Socket Listen を有効化
  "terminal.integrated.persistentSessionReviveProcess": "never",  // ターミナルの復元、再作成を行わない.
  "terminal.integrated.enablePersistentSessions": false           // ターミナルセッション履歴を保持しない
}

特定の SSH 鍵を利用する場合

SSH の認証は5回程度試行すると認証に失敗するため ssh-agent に複数鍵を登録している場合 SSH 接続出来ない場合がある。
その場合、 .ssh/configIdentitiesOnly yes, IdentityFile を設定します
IdentityFile公開鍵 で問題ありません。
IdentitiesOnly yes, IdentityFile ~/.ssh/host.pub の2つを書く必要があります。

1
2
3
IdentityFile
    You can also specify a public key file to use the corresponding private key that is loaded in ssh-agent(1) when the private key file is not present locally.
    また、秘密鍵ファイルがローカルに存在しない場合に、ssh-agent(1) にロードされる対応する秘密鍵を使用するために、公開鍵ファイルも指定できます。

ssh_config(5) - OpenBSD manual pages
.ssh/config
1
2
3
4
5
Host host
    User git
    HostName example.com
    IdentitiesOnly yes
    IdentityFile ~/.ssh/host.pub

ssh-add -l で鍵が見えたり見えなかったり

下記のように ssh-add -l で見えたり見えなくなったりの事象が発生した。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
PS C:\Users\naa0yama> ssh-add -l
256 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX cardno:XX_XXX_XXX (ED25519)
2048 SHA256:/XXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXX cardno:XX_XXX_XXX (RSA)
PS C:\Users\naa0yama> ssh-add -l
The agent has no identities.
PS C:\Users\naa0yama> ssh-add -l
256 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX cardno:XX_XXX_XXX (ED25519)
2048 SHA256:/XXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXX cardno:XX_XXX_XXX (RSA)
PS C:\Users\naa0yama> ssh-add -l
The agent has no identities.
PS C:\Users\naa0yama> ssh-add -l
256 SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX cardno:XX_XXX_XXX (ED25519)
2048 SHA256:/XXXXXXXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXXXX cardno:XX_XXX_XXX (RSA)

調査として gpg-agent を一度止め、詳細ログありで起動し、 ssh-add -l し続けると、鍵を表示出来ない時はそもそも 参照が来ていないので確認すると 1Password の ssh-agent 機能と競合していた…
ので、停止し解消した

参考情報

Hugo で構築されています。
テーマ StackJimmy によって設計されています。