GitHub のGPG署名を EdDSA にしてみる

# ことはじめ

[GitHub公式の対応GPGキー](https://docs.github.com/ja/authentication/managing-commit-signature-verification/generating-a-new-gpg-key)を見てみると、何気に EdDSA に対応している。

> - RSA
> - ElGamal
> - DSA
> - ECDH
> - ECDSA
> - EdDSA

先人もいるので、実際にEdDSA (今回は Ed25519) の署名を作って GitHub に登録する手順を自分用にまとめる。

https://weblog.shuuji3.xyz/post/2020-05-05-generate-and-sign-with-ed15519-gpg-key/


# 環境

某所の Ubuntu 22.04 LTS 環境。
fish なのはご容赦。

```console
❯ gpg --version
gpg (GnuPG) 2.2.27
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: /home/hoge/.gnupg
Supported algorithms:
Pubkey: RSA, ELG, DSA, ECDH, ECDSA, EDDSA
Cipher: IDEA, 3DES, CAST5, BLOWFISH, AES, AES192, AES256, TWOFISH,
        CAMELLIA128, CAMELLIA192, CAMELLIA256
Hash: SHA1, RIPEMD160, SHA256, SHA384, SHA512, SHA224
Compression: Uncompressed, ZIP, ZLIB, BZIP2
```

# 手順

## 鍵生成

`--expert` を使って鍵を生成する。
以下対話モード。

```console
❯ gpg --expert --full-gen-key
```

```console
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)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
   (9) ECC and ECC
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (13) Existing key
  (14) Existing key from card
Your selection?
```

`(11) ECC (set your own capabilities)` を選択

```console
Possible actions for a ECDSA/EdDSA key: Sign Certify Authenticate 
Current allowed actions: Sign Certify 

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? 
```

署名サイン用の `SC` なのでそのまま `(Q)`

```console
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 
```

今回は Ed25519 なので `(1) Curve 25519`

```console
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) 0
```
```console
Key does not expire at all
Is this correct? (y/N) y
```

無期限で勘弁してもらうのでここは素通り。

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

Real name: username
Email address: mail@addr.ess
Comment: comment
You selected this USER-ID:
    "username (comment) <mail@addr.ess>"

Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? 
```

立て続けに名前、メールアドレス、コメントを聞かれる。
今回は GitHub のアカウント情報を入力する前提で操作した。

上記での `username`, `mail@addr.ess`, `comment` は個々人におまかせするが、少なくともメールアドレスに関しては [GitHub 公式ドキュメント](https://docs.github.com/ja/authentication/managing-commit-signature-verification/generating-a-new-gpg-key)にあるとおり GitHub アカウント用の検証済みメールアドレスが必要。

ここまで作ると鍵のパスフレーズを求められるので入力。

完成した鍵が以下とする。
鍵のFingerprintは `FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF` と仮定。

```console
public and secret key created and signed.

pub   ed25519 9999-99-99 [SC]
      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
uid                      username (comment) <mail@addr.ess>

```

## サブキーを追加

この段階だと署名用、認証用のサブキーが無いので、先程の鍵を指定してサブキーを追加する。
サブキーも `Ed25519` がいいので再度 `--expert` で操作。

```console
❯ gpg --expert --edit-key FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
```

秘密鍵の ID は `EEEEEEEEEEEEEEEE` と仮定。

```console
sec  ed25519/EEEEEEEEEEEEEEEE
     created: 9999-99-99  expires: never       usage: SC  
     trust: ultimate      validity: ultimate
[ultimate] (1). username (comment) <mail@addr.ess>
```

### 署名用サブキー

```console
gpg> addkey
```

`addkey` コマンドを入力

```console
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
  (14) Existing key from card
Your selection? 
```

再度 `(11) ECC (set your own capabilities)` を選択

```console
Possible actions for a ECDSA/EdDSA key: Sign Authenticate 
Current allowed actions: Sign 

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? 
```

まずは署名用サブキーなので `S` で問題なし。 `(Q) Finished`

```console
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 
```

やっぱり Ed25519 なので `(1) Curve 25519`

```console
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) 0
```
```console
Key does not expire at all
Is this correct? (y/N) y
```

同じく無期限

```console
Really create? (y/N) 
```

念押しされるので `y`

鍵に変更が加わるのでパスフレーズを入力。

```console
sec  ed25519/EEEEEEEEEEEEEEEE
     created: 9999-99-99  expires: never       usage: SC  
     trust: ultimate      validity: ultimate
ssb  ed25519/DDDDDDDDDDDDDDDD
     created: 9999-99-99  expires: never       usage: S   
[ultimate] (1). username (comment) <mail@addr.ess>
```

出来上がったものは上記。
署名用サブキーの ID は `DDDDDDDDDDDDDDDD` と仮定。

### 認証用サブキー

```console
gpg> addkey
```

もういちど `addkey` コマンドを入力

```console
Please select what kind of key you want:
   (3) DSA (sign only)
   (4) RSA (sign only)
   (5) Elgamal (encrypt only)
   (6) RSA (encrypt only)
   (7) DSA (set your own capabilities)
   (8) RSA (set your own capabilities)
  (10) ECC (sign only)
  (11) ECC (set your own capabilities)
  (12) ECC (encrypt only)
  (13) Existing key
  (14) Existing key from card
Your selection? 
```

やっぱり `(11) ECC (set your own capabilities)`

```console
Possible actions for a ECDSA/EdDSA key: Sign Authenticate 
Current allowed actions: Sign 

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? 
```

次は認証用なので

 -  `(S) Toggle the sign capability` で署名可能を外す
 -  `(A) Toggle the authenticate capability` で認証可能にする

を連続で指定。
こんなふうに画面が遷移するはず。

```console
Possible actions for a ECDSA/EdDSA key: Sign Authenticate 
Current allowed actions: Sign 

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? s

Possible actions for a ECDSA/EdDSA key: Sign Authenticate 
Current allowed actions: 

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? a

Possible actions for a ECDSA/EdDSA key: Sign Authenticate 
Current allowed actions: Authenticate 

   (S) Toggle the sign capability
   (A) Toggle the authenticate capability
   (Q) Finished

Your selection? 
```

`Authenticate` のみになったので `(Q) Finished`

```console
Please select which elliptic curve you want:
   (1) Curve 25519
   (3) NIST P-256
   (4) NIST P-384
   (5) NIST P-521
   (6) Brainpool P-256
   (7) Brainpool P-384
   (8) Brainpool P-512
   (9) secp256k1
Your selection? 
```

ここも繰り返し。同じく Ed25519 なので `(1) Curve 25519`

```console
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) 0
```
```console
Key does not expire at all
Is this correct? (y/N) y
```

繰り返し。同じく無期限

```console
Really create? (y/N) 
```

念押しされるので `y`

鍵に変更が加わるので、もう一度パスフレーズを入力。

```console
sec  ed25519/EEEEEEEEEEEEEEEE
     created: 9999-99-99  expires: never       usage: SC  
     trust: ultimate      validity: ultimate
ssb  ed25519/DDDDDDDDDDDDDDDD
     created: 9999-99-99  expires: never       usage: S   
ssb  ed25519/CCCCCCCCCCCCCCCC
     created: 9999-99-99  expires: never       usage: A   
[ultimate] (1). username (comment) <mail@addr.ess>
```

これで認証用のサブキーも完了。
認証用サブキーの ID は `CCCCCCCCCCCCCCCC` と仮定。

### 保存

```console
gpg> save
```

最後に `save` コマンドを入れないと保存してくれないので、必ず `save`
対話モードはここで終わる。

出来上がった鍵は次のようになるはず。

```console
> gpg --list-secret-keys --keyid-format LONG
/home/hoge/.gnupg/pubring.kbx
-------------------------------------------------
sec   ed25519/EEEEEEEEEEEEEEEE 9999-99-99 [SC]
      FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
uid                 [ultimate] username (comment) <mail@addr.es>
ssb   ed25519/DDDDDDDDDDDDDDDD 9999-99-99 [S]
ssb   ed25519/CCCCCCCCCCCCCCCC 9999-99-99 [A]
```

## GitHub に貼り付けるための公開鍵

出来た署名から公開鍵を export

指定するのはこの鍵の Fingerprint

```console
> gpg --export --armor FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
-----BEGIN PGP PUBLIC KEY BLOCK-----

Loremipsumdolorsitamet,consecteturadipiscingelit,seddoeiusmodtem
porincididuntutlaboreetdoloremagnaaliqua.Utenimadminimveniam,qui
snostrudexercitationullamcolaborisnisiutaliquipexeacommodoconseq
uat.Duisauteiruredolorinreprehenderitinvoluptatevelitessecillumd
oloreeufugiatnullapariatur.Excepteursintoccaecatcupidatatnonproi
dent,suntinculpaquiofficiadeseruntmollitanimidestlaborum.Loremip
Loremipsumdolorsitamet,consecteturadipiscingelit,seddoeiusmodtem
porincididuntutlaboreetdoloremagnaaliqua.Utenimadminimveniam,qui
snostrudexercitationullamcolaborisnisiutaliquipexeacommodoconseq
uat.Duisauteiruredolorinreprehenderitinvoluptatevelitessecillumd
oloreeufugiatnullapariatur.Excepteursintoccaecatcupidatatnonproi
dent,suntinculpaquiofficiadeseruntmollitanimidestlaborum.Loremip
Loremipsumdolorsitamet,consecteturadipiscingelit,seddoeiusmodtem
porincididuntutlaboreetdoloremagnaaliqua.Utenimadminimveniam,qui
snostrudexercitationullamcolaborisnisiutaliquipexeacommodoconseq
uat.D=
=Lorem
-----END PGP PUBLIC KEY BLOCK-----

```

この公開鍵をコピー。

公式の [Adding a GPG key to your GitHub account](https://docs.github.com/ja/authentication/managing-commit-signature-verification/adding-a-gpg-key-to-your-github-account) を参考にして自分のアカウントに貼り付ければ完了。

## Git Config に署名を設定

ここまで来れば他と同じ。
`git config` でこのキーを指定してやる。

`user.signingkey` に鍵自身のID (今回の手順だと `EEEEEEEEEEEEEEEE`) を指定。

```console
❯ git config --global user.signingkey EEEEEEEEEEEEEEEE
```

署名用の設定を指定

```console
❯ git config --global commit.gpgsign true
❯ git config --global gpg.program (which gpg)
```

以上で操作は完了。
以後は commit すると `git log --show-signature` に署名がされているはず。