SSH秘密鍵を安全に管理するKryptoniteを使ってみた


#概要
[Kryptonite](https://krypt.co/)というサービスを見つけたので使ってみました。
KryptoniteはSSHの秘密鍵をスマートフォン上に保存し、PCなどで利用する際にはスマートフォンにPUSH通知が来て承認した場合のみ利用できるようにするものです。
利用イメージは上のサイトの動画を見るとすぐ掴めると思います。

秘密鍵が安全に管理できますし、複数PCでの秘密鍵の共有も安全に可能なので使ってみました。
通常であればPC紛失のことなどを考えると共有しないほうが好ましいかと思われますが（自分は普段分けてます）、Kryptoniteの場合はスマートフォン内に秘密鍵が保管されるので、PCごとに使い分けても意味が無いのかなと思っています（使い分けたほうが良い理由があれば教えてください）。

そしてOSSなのが嬉しいです。あとGoで書かれてるので読むと勉強になります。
とりあえず速攻使ってみたという記事なので、技術的な部分（krdが何してるかとか）は誰かが解説してくれることを祈ります。

# Kryptoniteが良い理由
他の方法と比べて、Kryptoniteが良い理由が以下に書かれています。
https://krypt.co/why_kryptonite/

簡単にまとめてみます（解釈違ってたらご指摘ください）。

## パスワード認証
- サービスごとに異なる複雑なパスワードを覚えるの不可能
- 毎回入力するのも面倒

## 公開鍵認証
- 秘密鍵は一般にユーザのホームディレクトリ（~/.ssh）に保存されるので、マルウェア等が勝手に盗み取れる
- パスフレーズ付きでも、パスワード入力時に復号されSSHエージェントに与えられるため、マルウェア等はSSHエージェントに保存された復号済みのキーを使用可能
- マルウェアはSSHエージェントして待ち受け、SSH_AUTH_SOCK変数を使用するようにSSHに指示することで平文で秘密鍵を入手可能（これどうやってやるのか知りたい）

## 2要素認証（2FA）
- 2FAを導入したい全サーバに設定変更が必要
- 多くの場合は6桁の数字を入れないといけないので面倒

## スマートカード
- USBを占有するハードウェアを購入して持ち運ばなくてはならない
- スマートカードの設定はワークステーションで行われるので、悪意を持った変更がされる可能性がある

# Kryptoniteのセキュリティ面
詳細はFAQに書いてあります。
https://krypt.co/faq/

簡単にまとめると、以下のことが主張されています。

- 秘密鍵はスマートフォン上で生成され、外に持ち出されることはない
	- 秘密鍵の役割はSSHハンドシェイクに署名をすることなので、署名が必要になったらスマートフォンに通知され、スマートフォン上で署名され署名だけが返される
- OSSとしてKryptoniteの全てのソースコードは公開されているので安全
- PCとスマートフォンの通信は全て暗号化され認証されている


# 環境
以下の環境で試しました。

- スマートフォン
	- iOS 10.3.1
- クライアントPC
	- macOS Sierra(10.12.4)
- サーバ
	- CentOS 6.8


# 使い方
ということで実際に使ってみます。
流れとしてはスマートフォンで鍵を生成し、それをPCでペアリングするだけです。一瞬で終わります。
サーバから見ると公開鍵認証しているだけなので設定変更は必要ないです。


## スマートフォンの設定

### アプリのインストール
どちらかインストールしましょう。自分はiOSを使いました。

- [iOS](https://itunes.apple.com/us/app/kryptonite-protect-your-ssh-private-key/id1161494806?mt=8)
- [Android](https://play.google.com/store/apps/details?id=co.krypt.kryptonite&pcampaignid=MKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1)

### 鍵の生成
アプリを起動すると、鍵の生成を求められます。
ここで感心したのが、右下からKey typeが選べるのですが、RSAだけでなくEd25519も選べました。最近使われることが多いですし良いですね。
iOSだとRSAの場合は4096-bitになるようです。

<img src="https://qiita-image-store.s3.amazonaws.com/0/56222/edf6aa6f-41b2-1c6b-93b3-99db92686a69.png" width=400>

ここではRSAで鍵を生成しました。

### メールアドレスの入力
次にメールアドレスの入力を求められます。
これは鍵の区別をつけるためのもののようなので、適当でも大丈夫な気がします（多分）。
一応自分はちゃんと入力しておきました。

<img src="https://qiita-image-store.s3.amazonaws.com/0/56222/5edc36fd-f180-ac07-9130-f184e2e7063f.png" width=400>


### PUSH通知の設定
PUSH通知を有効化します。
SSH利用時などにスマートフォンにPUSH通知を送る必要があるので、設定はほぼ必須かと思います。

<img src="https://qiita-image-store.s3.amazonaws.com/0/56222/f4610aff-5a11-1122-f9fc-904fabb7cb7b.png" width=400>

これが終わったあとはPC側の設定をします。

## PCの設定

### krのインストール
krはKryptoniteのスマートフォンアプリ内に保存された秘密鍵を利用できるようにするものです。
krdというSSHエージェントして常駐するようです。
https://github.com/kryptco/kr

インストール方法としては以下が紹介されてます。

```
$ curl https://krypt.co/kr | sh
```

ですがMacであればbrewでインストール可能のようなので、brewを使います。

```
$ brew install kryptco/tap/kr
```


### ペアリング
以下のコマンドを打つと、QRコードが表示されます。

```
$ kr pair
```


表示されたQRコードをスマートフォンのアプリで読み取るだけでペアリングは完了です。とても簡単です。

## サーバの設定
`kr pair` をしてペアリングが完了すると公開鍵が表示されます。
メモを忘れても `~/.ssh` 以下にファイルとして保存されているので、それをサーバのauthorized_keysに設定します（その設定は省略）。


```
$ cat ~/.ssh/id_kryptonite.pub | pbcopy
```

`kr me` でも表示可能です。


## 使ってみる
上記で設定したサーバにSSHしてみます。

```
$ ssh vagrant@192.168.33.10
Kryptonite ▶ Requesting SSH authentication from phone
Kryptonite ▶ Phone approval required. Respond using the Kryptonite app
```

この時、スマートフォンにPUSH通知がいきます。
それを押すと以下のように「一度だけ許可」、「3時間許可」、「拒否」の選択肢が表示されます。

<img src="https://qiita-image-store.s3.amazonaws.com/0/56222/02a7ea80-a7fc-4089-b36a-8f6dd9f9214d.png" width=400>

ここで許可を押すとスマートフォンのパスコードや指紋認証が聞かれ、その認証を通るとサーバにログインできます。


```
$ ssh vagrant@192.168.33.10
Kryptonite ▶ Requesting SSH authentication from phone
Kryptonite ▶ Phone approval required. Respond using the Kryptonite app
Kryptonite ▶ Success. Request Allowed ✔
Last login: Sat May  6 04:12:26 2017 from 192.168.33.1
Welcome to your Vagrant-built virtual machine.
[vagrant@localhost ~]$
```

当たり前ですが、Rejectを押すときちんとRejectされます。

```
$ ssh vagrant@192.168.33.10
Kryptonite ▶ Requesting SSH authentication from phone
Kryptonite ▶ Phone approval required. Respond using the Kryptonite app
Kryptonite ▶ Request Rejected ✘
sign_and_send_pubkey: signing failed: agent refused operation
no such identity: /Users/teppei/.ssh/id_ed25519: No such file or directory
no such identity: /Users/teppei/.ssh/id_ecdsa: No such file or directory
no such identity: /Users/teppei/.ssh/id_dsa: No such file or directory
```

# まとめ
秘密鍵を安全に保存可能なKryptoniteを使ってみました。
設定も非常に簡単で、PUSH通知が来たら承認するだけなので利便性も高いです。
自分はPCが3,4台あって秘密鍵の共有が面倒だったのですが、Kryptoniteを使えば簡単にかつ安全に共有できます。
ただサーバ側でKryptoniteを強制したりすることが出来ないため（サーバ側の設定が不要なのを売りにもしてますし）、会社などで全員に利用してもらおうとするのは難しそうです。

AD連携等可能な[有料版](https://krypt.co/pricing/)もあるようなので、気になる方は調べてみてください。