Git で署名付きCommitを行うメモ
GitHubとかでCommitを見てると、GnuPGで署名されたCommitや、
Signed-off-by: John Doe
で署名+GnuPGの署名のついたCommitがありますよね
やってみましょう
GnuPG
まずはGPGをOS X MarvericksにはGnuPGが入っていないため、インストール
(前のSnow Leopard/Lionには入ってたような気がしてたけど勘違いかも)
1 |
sudo port install gnupg2 |
前準備として.bashrcなどにgpg-agentと、TTYの設定をしておきます
(source .bashrcを忘れないように!)
1 2 3 4 5 |
#GnuPG2 pgrep -q gpg-agent || eval $(gpg-agent --daemon --write-env-file ${HOME}/.gpg-agent-info) [ -f ${HOME}/.gpg-agent-info ] && source ${HOME}/.gpg-agent-info export GPG_AGENT_INFO export GPG_TTY=`tty` |
鍵の生成
鍵が無いと始まらないので生成
昔鍵を無くしてREVOKEできなくて後悔したので2年でexpireするように作っておきます
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 |
[kota@MBP ~]$ gpg2 --gen-key gpg (GnuPG) 2.0.22; Copyright (C) 2013 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. Please select what kind of key you want: (1) RSA and RSA (default) (2) DSA and Elgamal (3) DSA (sign only) (4) RSA (sign only) Your selection? RSA keys may be between 1024 and 4096 bits long. What keysize do you want? (2048) 4096 Requested keysize is 4096 bits Please specify how long the key should be valid. 0 = key does not expire = key expires in n days w = key expires in n weeks m = key expires in n months y = key expires in n years Key is valid for? (0) 2y Key expires at 日 1/24 02:59:37 2016 JST Is this correct? (y/N) y GnuPG needs to construct a user ID to identify your key. Real name: John Doe Email address: johndoe@example.com Comment: What You Need Is What You Get!! You selected this USER-ID: "John Doe (What You Need Is What You Get!!) <johndoe@example.com>" Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? o You need a Passphrase to protect your secret key. |
鍵のIDをクリップボードにでもコピりましょう(この場合)5FE1D7EF
1 2 3 4 5 6 |
[kota@MBP ~]$ gpg2 --list-keys /Users/kota/.gnupg/pubring.gpg ------------------------------ pub 4096R/5FE1D7EF 2014-01-23 [expires: 2016-01-23] uid John Doe (What You Need Is What You Get!!!) <johndoe@example.com> sub 4096R/8DDF7B60 2014-01-23 [expires: 2016-01-23] |
公開鍵を鍵サーバーに送る(反映されるまでしばしかかります)
1 2 |
[kota@MBP ~]$ gpg2 --send-keys -v 5FE1D7EF gpg: sending key 5FE1D7EF to hkp server keys.gnupg.net |
登録されてるか調べるには?
1 2 3 4 5 6 7 |
[kota@MBP ~]$ gpg2 --search-keys johndoe@example.com gpg: searching for "johndoe@example.com" from hkp server keys.gnupg.net (1) John Doe (lol) <johndoe@example.com> 1024 bit DSA key BCBD4058, created: 2013-10-27 (2) John Doe <johndoe@example.com> 1024 bit DSA key A9034779, created: 2002-11-20 Keys 1-2 of 2 for "johndoe@example.com". Enter number(s), N)ext, or Q)uit > |
念のためrevoke keyも作っておきましょう
(万が一無くした時本当に残念です)
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 |
[kota@MBP ~]$ gpg2 --gen-revoke 5FE1D7EF > .gnupg/revoke.key sec 4096R/5FE1D7EF 2014-01-23 John Doe (What You Need Is What You Get!!!) <johndoe@example.com> Create a revocation certificate for this key? (y/N) y Please select the reason for the revocation: 0 = No reason specified 1 = Key has been compromised 2 = Key is superseded 3 = Key is no longer used Q = Cancel (Probably you want to select 1 here) Your decision? Enter an optional description; end it with an empty line: > Reason for revocation: Key has been compromised (No description given) Is this okay? (y/N) Please select the reason for the revocation: 0 = No reason specified 1 = Key has been compromised 2 = Key is superseded 3 = Key is no longer used Q = Cancel (Probably you want to select 1 here) Your decision? Enter an optional description; end it with an empty line: > Reason for revocation: Key has been compromised (No description given) Is this okay? (y/N) y You need a passphrase to unlock the secret key for user: "John Doe (What You Need Is What You Get!!!) <johndoe@example.com>" 4096-bit RSA key, ID 5FE1D7EF, created 2014-01-23 ASCII armored output forced. Revocation certificate created. Please move it to a medium which you can hide away; if Mallory gets access to this certificate he can use it to make your key unusable. It is smart to print this certificate and store it away, just in case your media become unreadable. But have some caution: The print system of your machine might store the data and make it available to others! |
Git+ GnuPGの設定
ここからやっとgitの設定
1 2 |
git config --global gpg.program gpg2 git config --global user.signingkey 5FE1D7EF |
これで完了!GPG-signed Commitをしてみましょう
ダイアログが出てきてpassphraseの入力が求められるはず
(最初の.bashrcんとこでgpg-agentを立ち上げているので、一回passphraseを入れればgpg-agentを終了するまで再入力は不要です)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[kota@MPB ~]$ mkdir repo [kota@MPB ~]$ cd repo/ [kota@MPB ~/repo]$ git init . Initialized empty Git repository in /Users/kota/repo/.git/ [kota@MPB ~/repo]$ touch README.md [kota@MPB ~/repo]$ git add README.md [kota@MPB ~/repo]$ git commit -S -m 'Sign !!!' You need a passphrase to unlock the secret key for user: "John Doe <johndoe@example.com>" 4096-bit RSA key, ID 5FE1D7EF, created 2014-01-24 [master e5fc7b0] Sign !!! 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 README.md |
おまちかね、署名を検証してみましょう
1 2 3 4 5 6 7 8 |
[kota@MBP ~/repo]$ git log --show-signature HEAD commit 5FE1D7EF gpg: Signature made 金 1/24 03:19:35 2014 JST using RSA key ID 5FE1D7EF gpg: Good signature from "John Doe <johndoe@example.com>" Author: John Doe <johndoe@example.com> Date: Fri Jan 24 03:18:56 2014 +0900 Sign !!! |
gpg: の行が青色になっていれば検証に成功しています
Signed-off-by: も一緒につけて、tag v0.1を付けるならこんな感じでしょうか
1 2 3 4 |
git tag -s v0.1 -m 'Tag + Sign' You need a passphrase to unlock the secret key for user: "John Doe <johndoe@example.com>" 4096-bit RSA key, ID 5FE1D7EF, created 2014-01-12 |
tagの検証
1 2 3 4 5 6 7 8 9 |
[kota@MBP ~/repo]$ git tag --verify v0.1 object 6ba00ec668ad9472bc5d5eeeff9f1f9fac396110 type commit tag v0.1 tagger John Doe <johndoe@example.com> 1390504243 +0900 Sign !!! gpg: Signature made 金 1/24 04:10:43 2014 JST using RSA key ID 5FE1D7EF gpg: Good signature from "John Doe <johndoe@example.com>" |
Good signatureが表示されてますね!
公開リポジトリの署名を検証する
さて、とりあえず自分のtag/commitは検証できるのですが、このまま他人の公開鍵を入れてないので当然検証できません。
試しにLinusの署名を検証してみましょうw
Linusの公開鍵を探して取り込みます
1 2 3 4 5 6 7 8 9 10 11 12 13 |
[kota@MBP ~]$ gpg2 --search-keys "torvalds@linux-foundation.org" gpg: searching for "torvalds@linux-foundation.org" from hkp server keys.gnupg.net (1) Linus Torvalds <torvalds@linux-foundation.org> 2048 bit RSA key 00411886, created: 2011-09-20 Keys 1-1 of 1 for "torvalds@linux-foundation.org". Enter number(s), N)ext, or Q)uit > 1 gpg: requesting key 00411886 from hkp server keys.gnupg.net gpg: key 00411886: public key "Linus Torvalds <torvalds@linux-foundation.org>" imported gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model gpg: depth: 0 valid: 2 signed: 1 trust: 0-, 0q, 0n, 0m, 0f, 2u gpg: depth: 1 valid: 1 signed: 0 trust: 1-, 0q, 0n, 0m, 0f, 0u gpg: next trustdb check due at 2016-01-12 gpg: Total number processed: 1 gpg: imported: 1 (RSA: 1) |
とりあえず今は彼を信頼しておきましょう
公開鍵に署名します
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[kota@MBP ~]$ gpg2 --sign-key "Linus Torvalds" pub 2048R/00411886 created: 2011-09-20 expires: never usage: SC trust: unknown validity: unknown sub 2048R/012F54CA created: 2011-09-20 expires: never usage: E [ unknown] (1). Linus Torvalds <torvalds@linux-foundation.org> pub 2048R/00411886 created: 2011-09-20 expires: never usage: SC trust: unknown validity: unknown Primary key fingerprint: ABAF 11C6 5A29 70B1 30AB E3C4 79BE 3E43 0041 1886 Linus Torvalds <torvalds@linux-foundation.org> Are you sure that you want to sign this key with your key "Kota Shiratsuka <kota@insaneworks.co.jp>" (73FA2F86) Really sign? (y/N) y You need a passphrase to unlock the secret key for user: "John Doe <johndoe@example.com>" 4096-bit RSA key, ID 5FE1D7EF, created 2014-01-12 |
Linuxのgit repoをcloneします。(本気で重いので注意)
1 2 3 4 5 6 7 8 9 10 11 12 |
[kota@MBP ~/Downloads]$ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git Cloning into 'linux'... remote: Counting objects: 3371568, done. remote: Compressing objects: 100% (509547/509547), done. remote: Total 3371568 (delta 2837672), reused 3366608 (delta 2832943) Receiving objects: 100% (3371568/3371568), 704.94 MiB | 3.88 MiB/s, done. Resolving deltas: 100% (2837672/2837672), done. Checking connectivity... done. Checking out files: 100% (45290/45290), done. git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git [kota@MBP ~/Downloads]$ cd linux [kota@MBP ~/Downloads/linux]$ |
Linux v3.13のtagにLinusの署名があるか確認するには、、?
1 2 3 4 5 6 7 8 |
[kota@MBP ~/Downloads/linux]$ git verify-tag v3.13 gpg: Signature made 月 1/20 11:40:23 2014 JST using RSA key ID 00411886 gpg: checking the trustdb gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model gpg: depth: 0 valid: 1 signed: 2 trust: 0-, 0q, 0n, 0m, 0f, 1u gpg: depth: 1 valid: 2 signed: 0 trust: 2-, 0q, 0n, 0m, 0f, 0u gpg: next trustdb check due at 2016-01-12 gpg: Good signature from "Linus Torvalds <torvalds@linux-foundation.org>" |
Good signatureがありますね!Linuxが署名しているとわかります。
これをどう使うか、、Linux Kernelほど巨大であればこのような仕組みは必須ですね。
小規模なプロジェクトでの有効活用はそうだな、、verifyしなきゃdeployが走らないシステムとか、、?ですかね?
ちょっと思いつかないですが、tagを打つ時は署名するのがよさげですね!
参考
A Git Horror Story: Repository Integrity With Signed Commits