GitLab(gitlab.com)に SSH 公開鍵認証でログインできるようにするまでのメモ(たぶん GitHub でも使える)

私は個人的なリポジトリのホスティング先に GitLab を利用しています。なぜ GitHub を使用しないのかというと(アカウントは持ってますよ)、別に宗教的な理由(具体的には、Microsoft の熱心なアンチとか)ではなく、ロゴがキツネっぽいタヌキだからです。私はキツネもタヌキも好きなので、その一点だけで GitLab を利用しています。別にネコやタコが嫌いなわけではないんですけどね。

閑話休題して、GitLab に Push したりするときにいちいちパスワードを入力しなければいけないのは非常に面倒だと感じていました。自分の場合、パスワードは自動生成されたぐちゃぐちゃの文字列をキーチェインで管理しているので、いちいち引っ張り出してくるのは非常に面倒なわけです。

で、SSH 公開鍵認証で面倒事を省略しようと考えました。私は記憶力がカスなのでパソコン買い換えたりしたらまた調べ直すことになるのは必至なので自分用のメモとして書いています。やってることは GitHub でも大して変わらないんじゃないかなぁ。

## 公開鍵認証概要

SSH で利用されている公開鍵による電子署名について軽く説明しておきます。といっても私も仕組みはよくわかってないのでだいぶ曖昧ですが。

電子署名には公開鍵と秘密鍵のペアが使われます。秘密鍵は署名の作成のために使われます。公開鍵は署名の検証のために使われます。秘密鍵で署名されたデータを、公開鍵で検証し、問題ないと確かめることで送信者が確かに想定している本人であると確信するというようなイメージですね。

ここで大事なのは、「秘密鍵から公開鍵は作れる」が「公開鍵から秘密鍵は(現実的な時間では)作れない」ということです。作れないので、公開鍵は名前の通り全世界にばらまいちゃっても問題ないわけです。公開鍵をあらかじめサービス側に教えておくのは印鑑登録のようなものです。印鑑(秘密鍵)は手元に置いておき、必要なときに渡すのは印影(署名済みデータ)のみです。印影と印鑑証明書を比較するのが検証というわけです。そして電子署名は印鑑証明書から印鑑を偽造するのがめちゃめちゃ難しいんです。

パスワード認証では、(大抵はハッシュ化とかされてるとはいえ)情報をネットワーク越しに送らなければいけませんが、公開鍵認証では秘密鍵そのものは手元に置いたままでいいので、よりセキュリティが担保されるわけです。

というわけで、SSH ログインでは公開鍵認証によって本人確認できます。秘密鍵は置きっぱなしでコマンドを叩くだけでいいので、手間も省けて万々歳です。

## 鍵ペアの生成

鍵ペアを生成します。一般的なシステムでは以下のコマンドでキーペアを生成できるはずです。

```shell
cd
mkdir .ssh
cd .ssh
ssh-keygen -t ed25519 -C "username@example.com pc-name"
```

`-t` オプションは鍵生成に使用するアルゴリズムを指定しています。Ed25519 は「エドワーズ曲線デジタル署名アルゴリズム」とかいうカッチョいい名前のアルゴリズムの実装の一つです。このアルゴリズムは旧来のアルゴリズムに比べて少ない鍵長で高いセキュリティを担保でき計算もそこそこ速いなどつよつよな特徴を多数持っていて、しばらくは安泰な感じだと思います。

`-C` オプションは公開鍵の末尾にコメントを付与します。これはのちのち登録した鍵の一覧とかにも表示されるので、分かりやすいのを付けるといいと思います。私の場合、個人を指定するためのメールアドレスと、個人的に端末につけている名前のペアにしました。複数の端末からログインすることを考えた場合、秘密鍵を持ち出して使い回すのはリスクなので、端末ごとに生成しようと思ったからですね。

このコマンドを叩くとパスフレーズの入力を求められます。が、シカトしてやりました。根拠は[ここ](https://freak-da.hatenablog.com/entry/20100901/p1)にありますが、かいつまんで言うと「秘密鍵が漏れてる時点で危険なのに覚えていられる程度のパスフレーズを設定してもあんま意味ない」という話です。zip のパスワードみたいなもんで手元に確保されてしまえば解析し放題というのはわかりやすい喩えですね。

Enter キー 2 回でシカトすると、`~/.ssh/id_ed25519` および `~/.ssh/id_ed25519.pub` みたいな感じで鍵ペアが生成されます。`.pub` が付いてる方が公開鍵なので、あとで中身をコピペして登録します。ついてない方は秘密鍵です。開く必要性すらないので、ほっときます。

## 公開鍵の登録

[GitLab の設定画面](https://gitlab.com/-/profile/keys)を開き、公開鍵をコピペし、キーを追加します。やることはそれだけ。有効期限はなしにすることもできますが、そんなに手間でもないのでそのままにしといていいんじゃないかと思います。パスフレーズの話は、ある程度の長さのパスフレーズを設定しておけば解析してる間に有効期限が切れるのでまあ多少意味はあるんですかね?　私は面倒くさがりなので再生成とかしなそうだしたぶん同じ鍵使い回すんで意味ないですけど。みんなはこんなものぐさ人間になっちゃだめだぞ。

余談ですが、たぶん電子署名の泣き所はここで、ここに攻撃者が持っている電子署名の公開鍵をソーシャルエンジニアリング的手法で登録させられると好き放題されます。「この公開鍵で検証できるデータは俺本人だよリスト」に部外者の署名を登録させられるので地獄が始まる……!

## ログイン設定の作成

SSH ログインのための設定ファイルを作成(ないし追記)します。`~/.ssh/config` ファイルをなければ作成し、末尾に次の感じで追記します。

```
Host gitlab
    HostName gitlab.com
    IdentityFile ~/.ssh/id_ed25519
    User git
```

各パラメータは目的に合わせてよしなに。

## ログイン

ログインします。

```shell
ssh gitlab -T
```

これで clone も push も自由自在です。

## 余談: 鍵の使いまわし是非

「ところで SSH の鍵ペアを使いまわしてもいいの?」という問題は誰しもぶち当たるものですが、これに対する私見を述べておきます。

まず、サービス間での使い回し……たとえば、GitLab で使用している鍵ペアを GitHub でも使うみたいなのは問題ないと思っています。上の方で印鑑に喩えた話をしましたが、自動車を買うときとマイホームを買うときで別々の実印を登録したりしないですよね?　っていうかできないハズ。~~じゃあなんで銀行印は実印と分けてるんだよっていうツッコミは密に密に~~

パスワードの使い回しが危険とかいうのは普通パスワードが流出したときに同じパスワードを使っていると全部侵入されてヤバいという文脈であって、電子署名では向こうが知っているのは公開鍵だけなので漏れようがないんですよね。量子コンピュータかなんかでスゴイ・手法が開発されて公開鍵から秘密鍵を逆算するのが簡単になったら話は違いますが、その場合使いまわししてなくてもオシマイなので同じことです。そんで、後述しますが理想的な管理では秘密鍵は門外不出なものなので、もし秘密鍵が流出しようものならそれはつまりお前のパソコンに侵入されているということであって他に気にすることあるだろって話になります。

その一方で、端末間の使い回しはやめとけって思います。といっても使い回し自体がまずいっていう話ではないです。サービス間で使い回すときは公開鍵だけあちこちに貼り付けるだけなのでいいんですが、別の端末からログインするなら署名を行うための秘密鍵もその端末にコピーしないといけないわけです。これが非常にまずい。だってどうやってセキュアに秘密鍵を受け渡すんですか?　ネット経由は当然絶対アカンです。じゃあ USB にでも入れてハードウェアで持ち歩きますか?　でも USB がウイルスに感染していない保証はどこにもないですし、なんならコンビニに置き忘れるかもしれません。よくあるインシデントの一つです。

そんなに手間じゃないですので、端末ごとに鍵ペアを生成して、作ったら触らずほっときましょう。というのが私見です。合ってますかね?