所要時間目安: 10〜15 分
0. 事前準備
-
ハードウェア: YubiKey 5 シリーズ(OpenPGP 3.x 対応)
-
ソフトウェア
- GnuPG 2.4 以降 (
gpg --version
で確認) - YubiKey Manager (
ykman
) - pinentry(macOS は
pinentry-mac
) - Git 2.35 以降
- GnuPG 2.4 以降 (
macOS なら
brew install gnupg yubikey-manager pinentry-mac
1. YubiKey OpenPGP アプレットの初期化 (初回のみ)
# **すべての OpenPGP データが消えます**
ykman openpgp reset --force
# 管理者 PIN / ユーザ PIN を変更
# 既定 admin PIN: 12345678, user PIN: 123456
ykman openpgp access change-pin --pin 123456 --new-pin <NEW_PIN>
ykman openpgp access change-admin-pin --admin-pin 12345678 --new-admin-pin <NEW_ADMIN_PIN>
# カード情報を設定(任意)
gpg --card-edit
> admin
> name
姓 名
> lang
ja
> quit
2. マスター鍵とサブ鍵を作成
推奨: オフライン PC でマスター鍵を作成し、サブ鍵のみ YubiKey に移動する。
gpg --full-generate-key
# 1) (9) ECC and ECC
# 2) (1) Curve25519 (ed25519)
# 3) 用途: SC (認証は後で追加)
# 4) 有効期限: 3y など
# 5) 名前とメール (GitHub 用メール)
KEYID の取得方法
生成した鍵の KEYID は以下のコマンドで確認できます(LONG 形式がおすすめ):
# 公開鍵一覧を長い形式で表示
gpg --list-keys --keyid-format LONG
# 秘密鍵(サブ鍵含む)の一覧
gpg --list-secret-keys --keyid-format LONG
出力例:
sec ed25519/ABCD1234EFGH5678 2025-05-12 [SC]
0123 4567 89AB CDEF 0123 4567 89AB CDEF 0123 4567
ed25519/
の後ろに続く 16 桁が LONG KEYID(8 桁は SHORT)。この値を <KEYID>
の箇所に置き換えてください。
サブ鍵を追加(署名・暗号・認証)
# 署名サブ鍵
gpg --edit-key <KEYID>
gpg> addkey
# → (10) ECC (sign only) を選択
# Curve25519 を選び、期限を設定
# ==> 署名 (S) 用サブ鍵完成
gpg> save
> **keytocard を実行すると?**
> 選択したサブ鍵の **秘密鍵本体はローカルから完全に削除** され、カード側にのみ保存されます。ローカルには **スタブ (鍵参照) だけ** が残り、`gpg --list-secret-keys` で `ssb>` と `card-no:` が付いた行として表示されます。したがって YubiKey を紛失すると復元できないため、必ず Step 4 の手順で秘密鍵バックアップを作成してから削除・移行を行ってください。
# 暗号サブ鍵
gpg --edit-key <KEYID>
gpg> addkey
# → (12) ECC (encrypt only) を選択
# Curve25519 を選び、期限を設定
# ==> 暗号 (E) 用サブ鍵完成
gpg> save
# 認証サブ鍵
gpg --edit-key <KEYID>
gpg> addkey
# → (10) ECC (sign only) を選択
# Curve25519 を選ぶ → 途中で Capabilities 画面が出たら `S` を無効化し `A` を有効化
# (expert モードの場合は `toggle` で切替可能)
# ==> 認証 (A) 用サブ鍵完成
gpg> save
Point: GnuPG 2.4 系では
addkey
のメニュー番号が(10) ECC (sign only)
/(12) ECC (encrypt only)
などに変わっています。上記番号を参考に、署名用・暗号用・認証用の 3 つのサブ鍵を個別に作成してください。
3. サブ鍵を YubiKey に移動
キー番号とカードスロットの対応
- 署名サブ鍵 → Signature slot (=
keytocard (1)
)- 暗号サブ鍵 → Encryption slot (=
keytocard (2)
)- 認証サブ鍵 → Authentication slot (=
keytocard (3)
)
カード側に既に鍵が入っているスロットは選択肢に出てきません。表示される番号は空いているスロットのみです。
gpg --edit-key <KEYID>
# 秘密鍵を表示
gpg> toggle
# 1. 署名サブ鍵を選択しカードへ移動
gpg> key 1 # "ssb ... usage: S" を選択
gpg> keytocard # プロンプト: (1) Signature key を選択
# 2. 暗号サブ鍵を選択しカードへ移動
gpg> key 2 # "ssb ... usage: E"
gpg> keytocard # プロンプト: (2) Encryption key が表示されていれば選択
# 3. 認証サブ鍵を選択しカードへ移動
gpg> key 3 # "ssb ... usage: A"
gpg> keytocard # プロンプト: (3) Authentication key
gpg> save
例: 署名サブ鍵を選択 (key 2
) したところ keytocard
で
Please select where to store the key:
(1) Signature key
(3) Authentication key
Your selection?
と出た場合、署名用なら 1、認証用として使いたいなら 3 を選びます。
移行後の検証
# カードに格納された鍵情報を確認
gpg --card-status
-
Signature key / Encryption key / Authentication key の 3 行すべてに鍵指紋が表示され、
created:
が表示されていればカードへの移行完了です。 -
Authentication key: [none]
と出る場合は認証サブ鍵がまだカードに移動していません。再度key 3
→keytocard
→(3) Authentication key
を実行してください。 -
ssb>
行にcard-no: xxxx
が付いているサブ鍵は カードに格納済み を示します。
# サブ鍵が "ssb>" (先頭 >) と表示され card-no が付いているか確認
gpg --list-secret-keys --keyid-format LONG
動作テスト:
# 署名テスト
echo "hello" | gpg --clearsign | gpg --verify -
# 暗号化テスト (自己宛)
echo "secret" | gpg -e -r <KEYID> | gpg -d
SSH 認証を使うなら: 認証サブ鍵を移動したあと、
echo "enable-ssh-support" >> ~/.gnupg/gpg-agent.conf && killall gpg-agent
で gpg-agent を SSH エージェントとして有効化し、ssh-add -L
で鍵が表示されるか確認します。
4. マスター鍵を安全にバックアップ & 削除
# 公開鍵
gpg --armor --export <KEYID> > pubkey.asc
# 秘密鍵バックアップ(オフライン保管推奨)
gpg --export-secret-keys <KEYID> > masterkey-backup.gpg
gpg --export-ownertrust > ownertrust.txt
# PC から秘密鍵を削除
gpg --delete-secret-keys <KEYID>
5. GitHub に公開鍵を登録
gpg --armor --export <KEYID> | pbcopy # Linux は xclip
- GitHub → Settings → SSH and GPG keys → New GPG key
- コピーした公開鍵を貼り付け Add GPG key
6. Git を設定
git config --global user.signingkey <KEYID>
git config --global commit.gpgsign true
git config --global gpg.program gpg
# macOS: pinentry を固定したい場合
echo "pinentry-program /opt/homebrew/bin/pinentry-mac" >> ~/.gnupg/gpg-agent.conf
killall gpg-agent
シェルに以下を追加(bash/zsh 共通):
echo 'export GPG_TTY=$(tty)' >> ~/.zshrc
eval "$(grep GPG_TTY ~/.zshrc)"
7. コミットを署名
git commit -S -m "Add README"
# 初回はカード PIN を要求される
push 後、GitHub 上で Verified バッジが表示されることを確認。
8. トラブルシューティング
症状 | 解決策 |
---|---|
signing failed: Inappropriate ioctl for device |
export GPG_TTY=$(tty) をシェル設定 |
gpg: signing failed: card error |
YubiKey を挿し直す / PIN ロックを確認 |
GitHub で「Unverified」 | 公開鍵メールとコミットメールが一致しているか確認 |
gpg: KEYTOCARD failed: Unusable secret key |
選択したサブ鍵はすでにカードに移動済み (ssb> + card-no: ) か、ローカルに秘密鍵が残っていない。gpg --list-secret-keys --keyid-format LONG で ssb> 状態を確認し、まだ card-no: が無い認証サブ鍵 (usage: A ) を選んで keytocard (3) を実行するか、バックアップから秘密鍵を再インポートしてから再試行 |
9. 2 本目の YubiKey でバックアップ運用
鍵ペアは 一度カードに移すと取り出せない ため、バックアップ用 YubiKey を作る場合は次の手順で “鍵バックアップ → 2 本目へ再書き込み” を行います。
前提: Step 4 で
masterkey-backup.gpg
とownertrust.txt
を安全な場所に保管済み。
手順(まだカードに移していない鍵がローカルに残っている前提)
重要: バックアップ用鍵を作る場合、最初の YubiKey に
keytocard
する前に このセクションの作業を実施してください。keytocard
した後では秘密鍵本体が失われるため、バックアップとして 2 本目にコピーできません(後述の回避策を参照)。
- 2 本目 YubiKey を初期化
ykman openpgp reset --force
ykman openpgp access change-pin --pin 123456 --new-pin <NEW_PIN_2>
ykman openpgp access change-admin-pin --admin-pin 12345678 --new-admin-pin <NEW_ADMIN_PIN_2>
-
オフライン PC でバックアップ鍵を復元
ここで秘密鍵とサブ鍵がローカルに“再び”存在する状態になるため、続くkeytocard
で 2 本目に書き込めます。
gpg --import masterkey-backup.gpg
gpg --import-ownertrust ownertrust.txt
-
鍵を 2 本目 YubiKey へ移動 — Step 3 と同じく
keytocard
で 3 スロットに書き込み。
gpg --edit-key <KEYID>
gpg> toggle
gpg> key 1 # 署名
gpg> keytocard (1)
# ...(暗号・認証サブ鍵も繰り返し)
gpg> save
- ローカル秘密鍵を再削除(忘れずに!)
gpg --delete-secret-keys <KEYID>
- 動作確認
gpg --card-status # 2 本目でも指紋が 3 行そろうか確認
gpg --sign -u <KEYID> -o /tmp/test.sig /etc/hosts && gpg --verify /tmp/test.sig
Tips
- 2 本の YubiKey は PIN を変えておくと管理しやすいです。
- 普段はバックアップキーをオフサイト(金庫等)に保管し、緊急時のみ使用する運用が安全です。
10. 参考リンク
Happy hacking!