gitのcommitを署名付きにして偽装対策！

## はじめに：gitのcommitterは簡単に偽装できます！

committerはめちゃくちゃ簡単に偽装することができてしまいます。
実際に違うユーザーに化けてcommit・pushしてみます。

やり方は.gitconfigに設定されているusername, emailを変更するだけです。

```
[user]
  name = nisemono
  email = nisemono@email.com
```

これだけで、簡単にnisemonoとしてcommitすることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622760/3a172898-33a8-459e-a8f7-b89a60b6a894.png)

今回は架空のemail, usernameを用いていますが、実際に存在する他人のemail、usernameを設定すればその人物にcommitを偽装できてしまいます。

これに対応するためにgitでは署名付きコミットというものが用意されています。

https://docs.github.com/ja/authentication/managing-commit-signature-verification/about-commit-signature-verification

>GPG、SSH、または S/MIME を使用して、ローカルでタグとコミットに署名できます。 これらのタグやコミットは GitHub で検証済みとしてマークされているため、他のユーザーはその変更が信頼できるソースからのものであると確信できます。

署名付きコミットをすることでコミットにverifiedマークがつき、そのコミットの信頼性を確保することができます。
何よりマークついてかっこいいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622760/41e4d947-fe72-6aea-2087-ac1283d898ba.png)

本記事では署名付きコミットを実現するまでの過程をご紹介します。

GPGでの作成もできますが、sshキーでもSigning keyの設定ができますので、今回はsshキーでの設定方法をご紹介します。
ただし、ssh鍵での署名はgit v2.34からの対応らしいので、必要によってアップデートをしてください。
## key作成・登録

ssh-keygenを実行して、keyを生成します。`-C`オプションにメールアドレスを入れます。

```
ssh-keygen -t ed25519 -C "sample@email.com"
```

生成したキーをsiging keys として登録します。
Githubのコンソールにて、settings -> SSH and GPG keysにて、公開鍵を登録してください。

```
cat ~/.ssh/id_ed25519.pub | pbcopy
```

Key typeは"Signing Key"にして、設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622760/96f2b2df-61f0-ce2d-64ad-7b3ca3aadbe7.png)

## ~/.ssh/allowed_singers作成

続いて、allowed_signersというファイルを作成します。
このファイルで、SSH署名付きコミットやタグを検証するときに許可された署名者の公開鍵リストを格納したファイルを指定します。
作成するパスはどこでも良いですが、自分は.sshの中に入れてしまっています。

以下のフォーマットで設定します。

```
<email> <pubkey>
```

設定例は以下です。

```
user@email.com ssh-ed25519 AAAAC3Nz...
```
## .gitconfig編集

続いて、.gitconfigを編集します。
追加するのは以下4点です。

- user.sigingekey
- gpg
- gpg.ssh
- commit

```diff
[user]
  name = user
  email = user@email.com
+ signingkey = Users/user/.ssh/id_ed25519.pub
+[gpg]
+ format = ssh
+[gpg "ssh"]
+ allowedSignersFile = /Users/user/.ssh/allowed_signers
+[commit]
+ gpgsign = true
```

ここまでの設定で、署名ができたと思います！

## 動作検証

正しく署名コミットができるか確認してみます。
ここまでの設定を行ったのちに任意のcommitをして、以下のコマンドを叩きます。

```
git log --show-signature
```

すると、正しく設定されていれば以下のように正しく署名ができていることがわかります。

```diff
commit 11d3a20d502232dd4eeca71c234d02b9a317 (origin/main)
+ Good "git" signature for user@email.com with ED25519 key SHA256:XXXXXX
Author: ohnuma-haw <user@email.com>
Date:   Mon Jan 1 00:00:00 2024 +0900

    sample commit
```

pushをすることでverifiedマークがつくことを確認できると思います！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3622760/702da132-7a64-49dc-9287-240c4209e1b1.png)

## (余談) lazygitでの署名付きcommit

ここからはlazygitを使っている方への設定情報です。
lazygitでは.gitconfig内でcommit.gpgsignをtrueに設定するとcommit時にエラーになります。

https://github.com/jesseduffield/lazygit/issues/1146

これに関しては上記Issueで紹介されているように、config.yamlで以下の設定をすることで回避できます。

```yaml
git:
  overrideGpg: true
```
## (余談)複数アカウントでの署名

Githubでは同一のssh鍵を複数アカウントに設定することはできませんので、アカウントごとに個別のキーを生成する必要があります。
commit毎にどのキーを使って署名をするかを意識するのはめんどくさいです。
そんな時には.gitconfig内で設定できるIncludeIfが便利です。

ぜひ、以下の記事をご覧いただければと思います。

https://qiita.com/haw_ohnuma/items/bd57a2fbf4928b41df53