光のエンジニア雑食記

光も闇も、あるんだよ

mac上でYubikey 5Cnanoにgpgの鍵を登録してgit commitに gpg signするまで

せっかくYubikeyをいろいろ買ったので、 YubikeyにPG鍵をのせて使おうぜ! の回。

gpg --full-gen-key でgenerateしたあとにyubikeyに乗せる方法もありますが、今回はYubikey上で直接GPG鍵を作成した。

いろんなサイトをみてもやはり引っかかったので、Yubikey上のGPG鍵で git commitにgpg signするまでの流れを備忘録として。

質問等あればブログ記事なりツイッターなりで質問ください。

実行環境

OS: macOS Mojave 10.14.5

Yubikey: Yubikey 5C nano

gpgは下記コマンドでインストールした。

brew install gpg2 pinentry-mac
mkdir -p ~/.gnupg
echo "pinentry-program /usr/local/bin/pinentry-mac" > ~/.gnupg/gpg-agent.conf
killall gpg-agent
gpg-agent --daemon

作業内容

gpgに使うPIN , Admin PINを変更する

どうやら、 gpg鍵使用時のPIN, Admin PINは PIV Cardとは違うっぽい?

Yubikey Managerで変更した内容はyubico-piv-tool と同じPIN, PUKだが、 gpgのPIN, Admin PINとは別物らしい。

よくわからないので補足大歓迎。

下記コマンドでyubikeyに接続

# gpg --card-edit

admin commandを許可

gpg/card> admin
Admin commands are allowed

admin commandが増えている

gpg/card> help
quit           quit this menu
admin          show admin commands
help           show this help
list           list all available data
name           change card holder's name
url            change URL to retrieve key
fetch          fetch the key specified in the card URL
login          change the login name
lang           change the language preferences
sex            change card holder's sex
cafpr          change a CA fingerprint
forcesig       toggle the signature force PIN flag
generate       generate new keys
passwd         menu to change or unblock the PIN
verify         verify the PIN and list all data
unblock        unblock the PIN using a Reset Code
factory-reset  destroy all keys and data
kdf-setup      setup KDF for PIN authentication
key-attr       change the key attribute

passwd コマンドでPINを変更する

gpg/card> passwd
gpg: OpenPGP card no. <card_no> detected

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

PINを変更する。

1を選択してEnterするとCUIが表示されcurrent PINとNew PINが求められる。

factory reset時のPINは 123456

Your selection? 1
<ここでCUI>
PIN changed.

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

次にAdmin PINを変更する。

factory reset時のAdmin PINは 12345678

Your selection? 3
PIN changed.

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

quitしてpasswdモードから戻る

Your selection? q

GPG鍵の鍵長を2048bitから4096bitに変更する

gpg rsaの鍵長はデフォルトで2048だが、これを4096に変更する。こちらは鍵の強さは誤差なので、変えても変えなくても良い。好みで。

鍵長の変更は key-attr modeで行える。これはadminコマンドに含まれる。

求められるPINはすべて Admin PIN

key-attrは3種類あり、下記3種の鍵長を連続で修正する。

  • Signature key
  • Encryption key
  • Authentication key

Signature key

gpg/card> key-attr
Changing card key attribute for: Signature key
Please select what kind of key you want:
   (1) RSA
   (2) ECC
Your selection? 1
What keysize do you want? (2048) 4096
<ここで Admin PINをいれる >
< 成功したら↓のメッセージがでる >
The card will now be re-configured to generate a key of 4096 bits

Encryption key

Changing card key attribute for: Encryption key
Please select what kind of key you want:
   (1) RSA
   (2) ECC
Your selection? 1
What keysize do you want? (2048) 4096
The card will now be re-configured to generate a key of 4096 bits

Authentication key

Changing card key attribute for: Authentication key
Please select what kind of key you want:
   (1) RSA
   (2) ECC
Your selection? 1
What keysize do you want? (2048) 4096

The card will now be re-configured to generate a key of 4096 bits

全部の鍵が終わったら自動的にkey-attrモードを抜ける。

verify コマンドを叩くと、Yubikeyのステータスが確認できる。

ket-attrで鍵長を変更したため、 Key attributes の項目が rsa4096 rsa4096 rsa4096 となっていることが確認できる。

gpg/card> verify

Reader ...........: Yubico Yubikey 4 OTP U2F CCID
Application ID ...: <application id>
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: <serial number>
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 ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

これで鍵長の変更が完了した。

さて準備が終わったのでGPG鍵をYubikey上で作るぞ

generate コマンドでGPG鍵を作成できる。

後のプロンプトは gpg --gen-key と変わらない。

gpg/card> generate

暗号鍵をYubikey外に保存するかしないか?

Make off-card backup of encryption key? (Y/n) y

デフォルトPINとAdmin PINの情報が流れたりする。

Please note that the factory settings of the PINs are
   PIN = '123456'     Admin PIN = '12345678'
You should change them using the command --change-pin

GPG鍵の有効期限を設定。

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) 2y
Key expires at Thu Jun 17 00:26:05 2021 JST
Is this correct? (y/N) y

次に、GPG鍵の名前やメールアドレスやコメントを設定。

GPG鍵で設定する Realname と、 Email address は、 git commit時のAuthor設定と一致している必要があるので注意。

4096bitだと鍵の生成のところがすごい長かった。1分くらい。 2048bitはもうちょっとはやい。

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

Real name: Suzuka Asagiri
Email address: gpg@example.com
Comment: Yubikey 5Cnano
You selected this USER-ID:
    "Suzuka Asagiri (Yubikey 5Cnano) <gpg@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: Note: backup of card key saved to '/Users/example/.gnupg/sk_<key_id>.gpg'
gpg: key <key_id> marked as ultimately trusted
gpg: revocation certificate stored as '/Users/example/.gnupg/openpgp-revocs.d/<key_id>.rev'
public and secret key created and signed.

GPG鍵がyubikey上に生成されていることを verify コマンドで確認する

gpg/card> verify

Reader ...........: Yubico Yubikey 4 OTP U2F CCID
Application ID ...: <application id>
Version ..........: 2.1
Manufacturer .....: Yubico
Serial number ....: <serial number>
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 : 17
Signature key ....: <signature key>
      created ....: 2019-06-17 15:26:19
Encryption key....: <encryption key>
      created ....: 2019-06-17 15:26:19
Authentication key: <authentication key>
      created ....: 2019-06-17 15:26:19
General key info..:
pub  rsa4096/<key-id> 2019-06-17 Suzuka Asagiri (Yubikey 5Cnano) <gpg@example.com>
sec>  rsa4096/<key-id>  created: 2019-06-17  expires: 2021-06-16
                                card-no: <card no>
ssb>  rsa4096/<key-id>  created: 2019-06-17  expires: 2021-06-16
                                card-no: <card no>
ssb>  rsa4096/<key-id>  created: 2019-06-17  expires: 2021-06-16
                                card-no: <card no>

Signature key 以下が [none] となっていたところが、情報が追加されていることが確認できた。

以上でYubikeyに直接GPG鍵の生成を行うことができた。

さあgit commitでgpg signしよう

gitの設定を行う

適当なディレクトリを作って、適当に設定して、適当にコミットしてみる。 何度もいうが、 git commit時の author の設定はGPG鍵で設定した Realname と、 Email address が一致している必要がある。

まずはユーザとgpgの設定

mkdir -p tmp
cd tmp
git init
git config --add user.name "Suzuka Asagiri"
git config --add user.email "gpg@example.com"
git config --add gpg.program gpg
git config --add commit.gpgsign true

singingkeyを設定するために、 gpg --list-keys でkey idを取得する。

# gpg --list-keys
/Users/example/.gnupg/pubring.kbx
---------------------------------
pub   rsa4096 2019-06-17 [SC] [expires: 2021-06-16]
      <ここにランダムな長いkeyのID>
uid           [ultimate] Suzuka Asagiri (Yubikey 5Cnano) <gpg@example.com>
sub   rsa4096 2019-06-17 [A] [expires: 2021-06-16]
sub   rsa4096 2019-06-17 [E] [expires: 2021-06-16]

長い鍵のIDを取得したら、 git configで設定する

git config --add user.singingkey <ここにランダムな長いkeyのID>

あとはコミット。 commit.gpgsign true を設定しているので、 commit時に -SはつけなくてもOK。

# date > a 
# git add a
# git commit -m "hello"

コミット時に、以下のようなPIN入力が求められたら、 一番最初に設定した PIN を入力する。

f:id:suzutan0s2:20190618022619p:plain
コミット時に要求されるPIN

PINが正しければ、無事にコミットが完了する。はず。

git log --show-signature で、正しくGPG signできていることを確認する。

# git log --show-signature
commit 214ee31452938d642f4cac44cfc2fda21b23eedb (HEAD -> master)
gpg: Signature made Tue Jun 18 02:25:27 2019 JST
gpg:                using RSA key <key_id>
gpg: Good signature from "Suzuka Asagiri (Yubikey 5Cnano) <gpg@example.com>" [ultimate]
Author: Suzuka Asagiri <gpg@example.com>
Date:   Tue Jun 18 02:25:27 2019 +0900

    hello

以上。

参考にしたところ