GitHub に登録した OpenPGP 公開鍵を取り出す

公開:2020/10/14
更新:2020/10/14
5 min読了の目安(約4900字IDEAアイデア記事

GitHub ではコミット時やタグ付与時の電子署名を検証できる OpenPGP 公開鍵を登録することができるが,登録した OpenPGP 公開鍵を REST API を使って任意に取り出すことができる。

たとえば私が登録している公開鍵の情報はこんな感じに取り出せる[1]

$ curl -s https://api.github.com/users/spiegel-im-spiegel/gpg_keys
[
  {
    "id": 1043333,
    "primary_key_id": null,
    "key_id": "B4DA3BAE7E20B81C",
    "raw_key": "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\n\r\n...\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n",
    "public_key": "...",
    "emails": [
      {
        "email": "spiegel.im.spiegel...",
        "verified": true
      }
    ],
    "subkeys": [
      {
        "id": 1043334,
        "primary_key_id": 1043333,
        "key_id": "4308C4946F760D3C",
        "raw_key": null,
        "public_key": "...",
        "emails": [

        ],
        "subkeys": [

        ],
        "can_sign": false,
        "can_encrypt_comms": true,
        "can_encrypt_storage": true,
        "can_certify": false,
        "created_at": "2020-10-13T22:07:23.000Z",
        "expires_at": null
      }
    ],
    "can_sign": true,
    "can_encrypt_comms": false,
    "can_encrypt_storage": false,
    "can_certify": true,
    "created_at": "2020-10-13T22:07:23.000Z",
    "expires_at": null
  }
]

一部 ... で省略しているがあしからず。

公開鍵は複数登録できるので配列構造になっている。たとえば最初の鍵を取り出したいのであれば jq コマンドを使って

$ curl -s https://api.github.com/users/spiegel-im-spiegel/gpg_keys | jq .[0]

などとすればよい。鍵IDがあらかじめ分かっているのなら

$ curl -s https://api.github.com/users/spiegel-im-spiegel/gpg_keys | jq '.[]|select(.key_id=="B4DA3BAE7E20B81C")'

などとすることもできる。 jq めっさ便利!

取り出した情報のうち raw_key 項目の内容が GitHub に実際に登録した OpenPGP 公開鍵データだ。これを取り出すには jq-r オプションを使って

$ curl -s https://api.github.com/users/spiegel-im-spiegel/gpg_keys | jq -r '.[]|select(.key_id=="B4DA3BAE7E20B81C")|.raw_key'
-----BEGIN PGP PUBLIC KEY BLOCK-----

...
-----END PGP PUBLIC KEY BLOCK-----

などとすればよい。この OpenPGP 公開鍵データはそのまま GnuPG 等にインポートできる。

$ curl -s https://api.github.com/users/spiegel-im-spiegel/gpg_keys | jq -r '.[]|select(.key_id=="B4DA3BAE7E20B81C")|.raw_key' | gpg --import

登録している公開鍵によっては raw_key 項目が null になっているものもあるようだ(登録時期が古いもの?)。この場合 OpenPGP 公開鍵として取り出すことは出来ないが,公開鍵パケットのみであれば public_key 項目から取り出すことは可能である。

ただし BASE64 で符号化してあるので base64 や openssl などのコマンドでバイナリデータに復号する必要がある。更に拙作の gpgpdump を使って取り出した公開鍵パケットを可視化することも可能である。

$ curl -s https://api.github.com/users/spiegel-im-spiegel/gpg_keys | jq -r '.[]|select(.key_id=="B4DA3BAE7E20B81C")|.public_key' | base64 -d | gpgpdump -u
Public-Key Packet (tag 6) (1198 bytes)
    Version: 4 (current)
    Public key creation time: 2013-04-28T10:29:43Z
    Public-key Algorithm: DSA (Digital Signature Algorithm) (pub 17)
    DSA p (3072 bits)
    DSA q (q is a prime divisor of p-1) (256 bits)
    DSA g (3070 bits)
    DSA y (= g^x mod p where x is secret) (3067 bits)

なお,公開鍵パケットのみでは OpenPGP 公開鍵として使うことは出来ないのであしからず[2]raw_key 項目はないがどうしても OpenPGP 公開鍵を入手したいのであれば,たとえば

$ curl -s https://api.github.com/users/spiegel-im-spiegel/gpg_keys | jq -r .[].key_id
B4DA3BAE7E20B81C

といった感じに鍵IDのリストを取り出すことはできるので,以下のように

$ gpg --recv-keys B4DA3BAE7E20B81C

鍵サーバから GnuPG 等にインポートするしかないだろう。

【2020-10-14 追記】

コメントで教えてもらったのだが(情報ありがとうございます),ユーザ・プロファイルの URL に .gpg をくっつけたら OpenPGP 公開鍵データが取れるようだ。私の場合なら

$ curl -s https://github.com/spiegel-im-spiegel.gpg
-----BEGIN PGP PUBLIC KEY BLOCK-----

...
-----END PGP PUBLIC KEY BLOCK-----

で取れる。なのでこのまま

$ curl -s https://github.com/spiegel-im-spiegel.gpg | gpg --import

とするか,あるいは直接

$ gpg --fetch-key https://github.com/spiegel-im-spiegel.gpg

とすれば GnuPG にインポートできる。また gpgpdump を使って

$ curl -s https://github.com/spiegel-im-spiegel.gpg | gpgpdump

とかすれば可視化もできる。

ちなみに複数の公開鍵を登録している場合は全ての鍵データを連結した状態で取り出せる。逆にひとつも公開鍵を登録してないユーザは

$ curl -s https://github.com/nokeyuser.gpg
-----BEGIN PGP PUBLIC KEY BLOCK-----
Note: This user hasn't uploaded any GPG keys.


=twTO
-----END PGP PUBLIC KEY BLOCK-----

みたいな表示になる。

参考

脚注
  1. curl コマンドを使って GitHub REST API でアクセスする際には -H "Accept: application/vnd.github.v3+json" オプションを付けるのが正しいが,なくてもとりあえず問題はないっぽい。今回は GraphQL API については割愛する。 ↩︎

  2. OpenPGP 公開鍵は公開鍵パケット,ユーザ ID パケット,署名パケットなど複数のパケットで構成されている。公開鍵パケットのみでは鍵自体を証明することが出来ないので,少なくとも GnuPG では使用することが出来ない。 ↩︎