GitとGPG署名
はじめに
GitコミットをGPG署名付きで行う場合に遭遇する作業まとめ。
Git
GIT_TRACE=1 GIT_GPG_COMMAND="gpg --pinentry-mode loopback" git commit -S -m "テスト"
GitHUBにKEYを登録するとき
--exportと--export-secret-keysのオプションでは結果が違う。
# --exportで登録できる。
gpg --armor --export XXXXXXXXXXXXXXXX | pbcopy
GPG cli
この記事のGPGバージョン
which gpg
/opt/homebrew/bin/gpg
gpg --version
gpg (GnuPG) 2.4.7
libgcrypt 1.11.0
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: /Users/USER_NAME/.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の概念
- 秘密鍵:Primary Key
- 秘密鍵:Subkey
- パスフレーズ
- 通常「最初に署名/復号などの操作をしたとき」に要求され、その後キャッシュされる。
- ロック
-
gpg-agentのキャッシュにパスフレーズを登録する事で起こる。
-
- アンロック
-
gpg-agentのキャッシュからパスフレーズを消去する事で起こる。
-
秘密鍵や秘密サブ鍵
表示例
gpg --list-secret-keys --keyid-format LONG
[keyboxd]
---------
sec rsa4096/ABCDEF1234567890 2025-04-16 [SC]
ABCDEF1234567890ABCDEF1234567890ABCDEF12
uid [ 究極 ] you <you@gmail.com>
ssb rsa4096/0987654321FEDCBA 2025-04-16 [E]
表示内容の意味
gpg --list-secret-keys --keyid-format LONG
[<ファイルヘッダー>]
---------
<行が秘密鍵を意味> <アルゴリズムと鍵長>/<秘密鍵> <鍵の生成日> [<鍵の用途フラグ>]
< 40 桁フィンガープリント>
<行がUserIDを意味> [ <信頼度> ] <YOUR NAME> <youremail@domain.com>
<行が秘密サブ鍵を意味> rsa4096/<秘密サブ鍵> <鍵の生成日> [<鍵の用途フラグ>]
キーグリップ: keygrip
sec rsa2048 2019-01-01 [SC]
ABCDEF1234567890ABCDEF1234567890ABCDEF12 ←これがkeygrip
uid Your Name <you@example.com>
GPGでやりたいこと
キーを新規作成
対話形式で作成される。
全部デフォルトで設定。
1) 鍵を生成(例:Ed25519 が推奨)
gpg --full-generate-key
gpg (GnuPG) 2.4.8; Copyright (C) 2025 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.
Please select what kind of key you want:
(1) RSA and RSA
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(9) ECC (sign and encrypt) *default*
(10) ECC (sign only)
(14) Existing key from card
Your selection?
Please select which elliptic curve you want:
(1) Curve 25519 *default*
(4) NIST P-384
(6) Brainpool P-256
Your selection?
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)
Key does not expire at all
Is this correct? (y/N) y
GnuPG needs to construct a user ID to identify your key.
Real name: <your name>
Email address: your@email.com
Comment:
You selected this USER-ID:
"your name <your@email.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.
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: revocation certificate stored as '/Users/your name/.gnupg/openpgp-revocs.d/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.rev'
public and secret key created and signed.
pub ed25519 2025-06-22 [SC]
ABCDEF1234567890ABCDEF1234567890ABCDEF12
uid your name <your@email.com>
sub cv25519 2025-06-22 [E]
2) ID を確認
gpg --list-secret-keys --keyid-format LONG
# → sec ed25519/XXXXXXXXXXXXXXXX の XXXXXXXXXXXXXXXX が KeyID
3) Git に設定
git config --global user.signingkey XXXXXXXXXXXXXXXX
4) 既定で署名したいなら
git config --global commit.gpgsign true
パスフレーズを変更
パスフレーズは通常「最初に署名/復号などの操作をしたとき」に要求され、その後キャッシュされる。
パスフレーズを変更することはできるが、古いパスフレーズの入力を求められるので、パスフレーズを忘れた場合は鍵自体を作り直すしかない。
# ターミナルで該当キーを編集モードにする
gpg --edit-key <KEY_ID>
gpg> passwd
# 古いパスフレーズと新しいパスフレーズを入力
gpg> save
鍵の開錠と施錠
キャッシュ TTLを指定する
1. ~/.gnupg/gpg-agent.confに追記
# キャッシュを 1 時間(3600 秒)に設定
default-cache-ttl 3600
# 最大キャッシュ時間を 1 日(86400 秒)に設定
max-cache-ttl 86400
2. 再読み込み
gpgconf --reload gpg-agent
手動で開錠、施錠 gpg-preset-passphrase
# 秘密鍵一覧と keygrip を表示
gpg --with-keygrip -K
sec rsa2048 2019-01-01 [SC]
ABCDEF1234567890ABCDEF1234567890ABCDEF12 ← これが keygrip
uid Your Name <you@example.com>
# アンロック(キャッシュ登録)
# keygrip 部分を自分のものに置き換えてください
echo -n "your_passphrase" | \
gpg-preset-passphrase --preset --passphrase-fd 0 ABCDEF1234567890ABCDEF1234567890ABCDEF12
# ロック(キャッシュ消去)
gpg-preset-passphrase --forget ABCDEF1234567890ABCDEF1234567890ABCDEF12
手動で開錠、施錠 gpg-connect-agent
# 秘密鍵一覧と keygrip を表示
gpg --with-keygrip -K
sec rsa2048 2019-01-01 [SC]
ABCDEF1234567890ABCDEF1234567890ABCDEF12 ← これが keygrip
uid Your Name <you@example.com>
# アンロック
gpg-connect-agent <<EOF
PRESET_PASSPHRASE --passphrase your_passphrase ABCDEF1234567890ABCDEF1234567890ABCDEF12
EOF
# ロック
gpg-connect-agent <<EOF
FORGET_PASSPHRASE ABCDEF1234567890ABCDEF1234567890ABCDEF12
EOF
現在のキャッシュ時間を確認する
gpg-connect-agent 'keyinfo --list' /bye
エラー
git commit 署名できない。
エラー内容
git -c user.useConfigOnly=true commit --quiet --allow-empty-message --file -
error: gpg failed to sign the data:
gpg: Note: database_open 134217901 waiting for lock (held by 20034) ...
gpg: Note: database_open 134217901 waiting for lock (held by 20034) ...
gpg: Note: database_open 134217901 waiting for lock (held by 20034) ...
gpg: Note: database_open 134217901 waiting for lock (held by 20034) ...
gpg: Note: database_open 134217901 waiting for lock (held by 20034) ...
gpg: keydb_search failed: Operation timed out
gpg: skipped "764FC4E2BB159C33": Operation timed out
[GNUPG:] INV_SGNR 0 764FC4E2BB159C33
[GNUPG:] FAILURE sign 134250628
gpg: signing failed: Operation timed out
fatal: failed to write commit object
# 古いロックファイルを削除する
rm -f ~/.gnupg/*.lock
rm -f ~/.gnupg/public-keys.d/*.lock
# gpgエージェントの再起動
gpgconf --kill gpg-agent
gpgconf --launch gpg-agent
# テスト
echo "test" | gpg --clearsign
整理中
# 秘密鍵の一覧表示
gpg --list-secret-keys --keyid-format LONG
# 対象キーの信頼度を変更
gpg --edit-key <KEY_ID>
gpg --fingerprint --fingerprint <NAME>
# pgp-agentのリロード
gpgconf --reload gpg-agent
Discussion