Gitコミット署名しよう

GnuPGはいつのまにか導入済み
❯ gpg --version
gpg (GnuPG) 2.3.2
libgcrypt 1.9.4
Copyright (C) 2021 Free Software Foundation, Inc.
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: /Users/kawarimidoll/.gnupg
サポートしているアルゴリズム:
公開鍵: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
暗号方式: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256,
TWOFISH, CAMELLIA128, CAMELLIA192, CAMELLIA256
AEAD: EAX, OCB
ハッシュ: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
圧縮: 無圧縮, ZIP, ZLIB, BZIP2
pinentry-mac
を導入
❯ brew install pinentry-mac
(略)
❯ echo "pinentry-program $(which pinentry-mac)" >> ~/.gnupg/gpg-agent.conf
鍵生成
❯ gpg --full-gen-key

❯ gpg --full-gen-key
gpg (GnuPG) 2.3.2; Copyright (C) 2021 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.
ご希望の鍵の種類を選択してください:
(1) RSA と RSA
(2) DSA と Elgamal
(3) DSA (署名のみ)
(4) RSA (署名のみ)
(9) ECC (署名と暗号化) *デフォルト
(10) ECC (署名のみ)
(14) カードに存在する鍵
あなたの選択は? 1
RSA 鍵は 1024 から 4096 ビットの長さで可能です。
鍵長は? (3072) 4096
要求された鍵長は4096ビット
鍵の有効期限を指定してください。
0 = 鍵は無期限
<n> = 鍵は n 日間で期限切れ
<n>w = 鍵は n 週間で期限切れ
<n>m = 鍵は n か月間で期限切れ
<n>y = 鍵は n 年間で期限切れ
鍵の有効期間は? (0)
鍵は無期限です
これで正しいですか? (y/N) y
GnuPGはあなたの鍵を識別するためにユーザIDを構成する必要があります。
本名: kawarimidoll
電子メール・アドレス: xxx@xxx.com
コメント:
次のユーザIDを選択しました:
"kawarimidoll <xxx@xxx.com>"
名前(N)、コメント(C)、電子メール(E)の変更、またはOK(O)か終了(Q)? O
たくさんのランダム・バイトの生成が必要です。キーボードを打つ、マウスを動か
す、ディスクにアクセスするなどの他の操作を素数生成の間に行うことで、乱数生
成器に十分なエントロピーを供給する機会を与えることができます。
(ここでpinentryが開いてパスフレーズを入力 もたもたしてると終了される)
gpg: /Users/kawarimidoll/.gnupg/trustdb.gpg: 信用データベースができました
gpg: 鍵9DF908CC763A2BF4を究極的に信用するよう記録しました
gpg: ディレクトリ'/Users/kawarimidoll/.gnupg/openpgp-revocs.d'が作成されました
gpg: 失効証明書を '/Users/kawarimidoll/.gnupg/openpgp-revocs.d/2CDDE4FEEAF29708ED0C3C399DF908CC763A2BF4.rev' に保管しました。
公開鍵と秘密鍵を作成し、署名しました。
pub rsa4096 2021-09-20 [SC]
2CDDE4FEEAF29708ED0C3C399DF908CC763A2BF4
uid kawarimidoll <kawarimidoll+git@gmail.com>
sub rsa4096 2021-09-20 [E]
これでキー作成完了
gpg -k
で生成結果を確認(究極ってかっこいいな…)
❯ gpg -k
gpg: 信用データベースの検査
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: 深さ: 0 有効性: 1 署名: 0 信用: 0-, 0q, 0n, 0m, 0f, 1u
/Users/kawarimidoll/.gnupg/pubring.kbx
--------------------------------------
pub rsa4096 2021-09-20 [SC]
2CDDE4FEEAF29708ED0C3C399DF908CC763A2BF4
uid [ 究極 ] kawarimidoll <xxx@xxx.com>
sub rsa4096 2021-09-20 [E]

生成した鍵をエクスポート
❯ gpg -a --export "kawarimidoll+git@gmail.com" > pubkey.gpg
❯ gpg -a --export-secret-key "kawarimidoll+git@gmail.com" > seckey.gpg
(secret-keyの出力はパスフレーズ入力必要)
GitHubの設定のSSH and GPG keysでNew GPG Keyを選択
pubkeyの内容をコピペ
cat pubkey.gpg | pbcopy
これで登録完了

Gitコミット時に生成したGPGが使われるよう設定
なおuser.signingkey
に登録するキーIDはgpg -k
で表示されるpub rsa4069 日付 [SC]
の次の行の文字列
❯ git config --global gpg.program `which gpg`
❯ git config --global commit.gpgsign true
❯ git config --global user.signingkey "2CDDE4FEEAF29708ED0C3C399DF908CC763A2BF4"
❯ git config --get-regexp 'gpg|sign'
gpg.program /opt/homebrew/bin/gpg
commit.gpgsign true
user.signingkey 2CDDE4FEEAF29708ED0C3C399DF908CC763A2BF4
なお上記の設定で~/.gitconfig
に書き込んだものの自分のユースケースの関係上~/.gitconfig.local
に移動した

git commitするとpinentryが起動しパスフレーズの入力が求められる
keep phraseにチェックを入れれば2回目以降は不要になるぽい
設定完了!

コミットできなくなった なにか壊したかもしれん

gpg --list-secret-keys --keyid-format LONG
してみたところssbに[S]
フラグが付いていない
❯ gpg --list-secret-keys --keyid-format LONG
gpg: error reading symlink '/proc/curproc/file': No such file or directory
gpg: *警告*: サーバ'gpg-agent'はこちらより古いです(2.3.2 < 2.3.3)
gpg: 注意: 古いサーバは、重要なセキュリティの修正が欠如しているかもしれません。
gpg: 注意: "gpgconf --kill all"コマンドを使って再起動してください。
/Users/kawarimidoll/.gnupg/pubring.kbx
--------------------------------------
sec rsa4096/xxxxx 2021-09-20 [SC]
xxxxx
uid [ 究極 ] kawarimidoll <kawarimidoll+git@gmail.com>
ssb rsa4096/xxxxx 2021-09-20 [E]
でもスクラップのログを見る限り前からついていなかったんだよなあ…
No such file or directory
が出てるしなにかの間違いでデータを消してしまったのかもしれない

記事に従ってみたが失敗
❯ gpg --edit-key kawarimidoll
gpg: error reading symlink '/proc/curproc/file': No such file or directory
gpg (GnuPG) 2.3.3; Copyright (C) 2021 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: *警告*: サーバ'gpg-agent'はこちらより古いです(2.3.2 < 2.3.3)
gpg: 注意: 古いサーバは、重要なセキュリティの修正が欠如しているかもしれません。
gpg: 注意: "gpgconf --kill all"コマンドを使って再起動してください。
秘密鍵が利用できます。
sec rsa4096/xxxxx
作成: 2021-09-20 有効期限: 無期限 利用法: SC
信用: 究極 有効性: 究極
ssb rsa4096/xxxxx
作成: 2021-09-20 有効期限: 無期限 利用法: E
[ 究極 ] (1). kawarimidoll <xxx@xxx.com>
gpg> key 1
sec rsa4096/xxxxx
作成: 2021-09-20 有効期限: 無期限 利用法: SC
信用: 究極 有効性: 究極
ssb* rsa4096/xxxxx
作成: 2021-09-20 有効期限: 無期限 利用法: E
[ 究極 ] (1). kawarimidoll <xxx@xxx.com>
gpg> change-usage
副鍵の使用法を変更します。
このRSA鍵にありうる操作: Sign Encrypt Authenticate
現在の認められた操作: Encrypt
(S) 署名機能を反転する
(E) 暗号機能を反転する
(A) 認証機能を反転する
(Q) 完了
あなたの選択は? s
このRSA鍵にありうる操作: Sign Encrypt Authenticate
現在の認められた操作: Sign Encrypt
(S) 署名機能を反転する
(E) 暗号機能を反転する
(A) 認証機能を反転する
(Q) 完了
あなたの選択は? q
gpg: 署名に失敗しました: No pinentry
gpg: make_keysig_packet failed: No pinentry
gpg> save
鍵は無変更なので更新は不要です。
pinentry-macは導入済みなんだが…
出力に従ってkillしてみるか

🤔
❯ gpgconf --kill all
gpgconf: error reading symlink '/proc/curproc/file': No such file or directory

メッセージ出てたわ
gpg: *警告*: サーバ'gpg-agent'はこちらより古いです(2.3.2 < 2.3.3)
gpg: 注意: 古いサーバは、重要なセキュリティの修正が欠如しているかもしれません。
gpg: 注意: "gpgconf --kill all"コマンドを使って再起動してください。
秘密鍵が利用できます。
鍵を設定したときはgnupg
が2.3.2だったんだけど今朝brew updateで2.3.3に更新されてる
これが問題だわ

あれ?ダメもとでもう一回やったらコミットできた
gpgconf --kill all
でエラーメッセージは出てるけど終了ステータスは成功になってたので処理としてはOKだったみたいだ

PCの移行(クリーンインストール)
上記記事に記載あり~
❯ gpg -k
gpg: ディレクトリ'/Users/kawarimidoll/.gnupg'が作成されました
gpg: keybox'/Users/kawarimidoll/.gnupg/pubring.kbx'が作成されました
gpg: /Users/kawarimidoll/.gnupg/trustdb.gpg: 信用データベースができました
~
❯ gpg -k
この時点ではgpg -k
しても何も表示されない
元の環境から鍵を持ってきて反映させる
なんかpinentryが起動しないのでcli上でパスフレーズを手入力→その後gpgconf --kill all
して再度commitしようとするときにpinentryが動いた
❯ gpg --import ./seckey.gpg
gpg: 鍵xxxxx:"kawarimidoll <xxxxx@xxxxx.com>"変更なし
gpg: 鍵xxxxx: 秘密鍵をインポートしました
gpg: 処理数の合計: 1
gpg: 変更なし: 1
gpg: 秘密鍵の読み込み: 1
gpg: 秘密鍵のインポート: 1
~
❯ gpg -k
/Users/kawarimidoll/.gnupg/pubring.kbx
--------------------------------------
pub rsa4096 2021-09-20 [SC]
xxxxxxxx
uid [ 不明 ] kawarimidoll <xxxxxxxx@xxxxxxxx.com>
sub rsa4096 2021-09-20 [E]
良さそう

忘れずにやる:
# pinentry-macの反映
echo "pinentry-program $(which pinentry-mac)" >> ~/.gnupg/gpg-agent.conf
# gpgの設定、.gitconfig.localへのコピペ
git config --global gpg.program `which gpg`
git config --global commit.gpgsign true
git config --global user.signingKey "xxx"
# error: gpg failed to sign the dataが出た場合の対処
gpgconf --kill all
OK

またなんか壊れたかも
gpg --list-secret-keys --keyid-format LONG
もgpg -k
もエラーは出ない
以前の表示と変わらないように見えるが…

gpgconf --kill all
したら直った よかった(?)

archlinux環境でも対応
.gitconfig.local
をscpして移動、homebrewのgpgを/usr/bin/gpg
に修正
kawarimidoll@archdoll ~ % gpg -k
gpg: directory '/home/kawarimidoll/.gnupg' created
gpg: keybox '/home/kawarimidoll/.gnupg/pubring.kbx' created
gpg: /home/kawarimidoll/.gnupg/trustdb.gpg: trustdb created
kawarimidoll@archdoll ~ % gpg --import ./git_gpg/seckey.gpg
gpg: key xxx: public key "kawarimidoll <xxx>" imported
gpg: key xxx/9DF908CC763A2BF4: error sending to agent: Timeout
gpg: error building skey array: Timeout
gpg: error reading './git_gpg/seckey.gpg': Timeout
gpg: import from './git_gpg/seckey.gpg' failed: Timeout
gpg: Total number processed: 0
gpg: imported: 1
gpg: secret keys read: 1
2 kawarimidoll@archdoll ~ % gpg --import ./git_gpg/seckey.gpg
gpg: key xxx: "kawarimidoll <xxx>" not changed
gpg: key xxx: secret key imported
gpg: Total number processed: 1
gpg: unchanged: 1
gpg: secret keys read: 1
gpg: secret keys imported: 1
kawarimidoll@archdoll ~ %
(1回目のimportではモタモタしててtimeoutになった)
しかしコミットしようとしたらfailedしてしまった
kawarimidoll@archdoll ~/dotfiles (git)-[master] % git commit -m 'chore: update yay-list'
error: gpg failed to sign the data:
[GNUPG:] KEY_CONSIDERED xxx 2
[GNUPG:] BEGIN_SIGNING H8
[GNUPG:] PINENTRY_LAUNCHED 17322 curses 1.2.1 - xterm-256color - - 1000/1000 0
gpg: signing failed: Inappropriate ioctl for device
[GNUPG:] FAILURE sign xx
gpg: signing failed: Inappropriate ioctl for device
fatal: failed to write commit object
gpg: signing failed: Inappropriate ioctl for device
で検索したところ以下を発見
shell設定で以下をexport
export GPG_TTY=$(tty)
再度パスフレーズを求められたがコミット成功!
kawarimidoll@archdoll ~/dotfiles (git)-[master] % git commit -m 'chore: update yay-list'
[master 85cc816] chore: update yay-list
1 file changed, 5 insertions(+), 1 deletion(-)
kawarimidoll@archdoll ~/dotfiles (git)-[master] %
pushのときにgithub signinを求められて対応 :ok:

gpg: WARNING: unsafe permissions on homedir '/Users/kawarimidoll/.gnupg'
が出た
以下のgistを実行する