SSHについて理解できたとこまでまとめてみた

#SSHについて調べてみたのでまとめる
SSHについて全く知らなかった私が、自分なりに理解したところをまとめていきたいと思います。
間違っている箇所があると思いますので、ぜひ編集リクエスト、コメントを頂けますと幸いです。

##調べる前の私のレベル
- サーバに入ったことがない
- SSH使ってサーバに入ってみたことがない
- どういう仕組みでサーバに入れるか知らない
- 公開鍵認証について少ししか知らない
- 公開鍵、秘密鍵の知識は多少あった

ではまとめてみます。

### SSHとは？
暗号化や認証で、安全にリモートホスト間通信をするためのプロトコル。

なぜ安全性を考慮しなければならないのでしょうか？
それは、ネット上の通信経路には盗聴の危険性がつきまとうからです。
もし通信内容が平文（暗号化されていない状態）で流れてしまっている場合、
その内容を悪意ある第３者に盗聴されたらパスワードやアカウントを暴かれてしまう可能性があります。
私は使ったことがありませんが、telnetというSSHと同じようにリモートホスト間を通信するためのプロトコルがあったそうですが、こちらは暗号化はされていないそうです。

SSHによって通信経路に流れてきた情報は、その時点で**暗号化**されているので、安全性が高まります。

###２つの暗号化技術
SSHを知る上で知っておいてほしい技術があります。

- 共通鍵暗号方式
- 公開鍵暗号方式

例えばネコさんがイヌさんに内緒の文書を送るとします。
ネコさんは文書を暗号化し、イヌさんはそのカギに対応する復号鍵で復号することで中身を見ることができます。
この暗号化、復号に使われる鍵が、共通であるか、別物であるかという違いがあります。

####共通鍵暗号方式
字のごとく、共通の鍵を使って暗号化、復号を行う方式です。
####公開鍵暗号方式
一方こちらは、異なる鍵を使って暗号化、復号を行う方式です。
こちらの方式は、公開鍵と秘密鍵という鍵となるデータを使って暗号化と復号をしています。
公開鍵で暗号化したら、それに対応する秘密鍵でしか復号はできません。
逆もまた然りで、秘密鍵で暗号化したら、それに対応する公開鍵でしか復号はできません。
この鍵のセットをキーペアと呼んだりします。

上記２つの方式には、メリット・デメリットが存在します。

####メリット・デメリット

| 方式   |処理負荷の重さ |    配送問題 |
|:-----------------|:------------------|:------------------|
| 共通鍵暗号方式|シンプルな方式なのであまり負荷がかからない |  問題を解決するために工夫が必要  |
| 公開鍵暗号方式|仕組みが少々複雑なので負荷がかかる| 問題ない|

共通鍵暗号方式のほうが共通の鍵で暗号化・復号を行うので、公開鍵暗号方式と比較すると処理負荷はあまりかからないというメリットがあります。
しかし、公開鍵暗号方式では鍵配送問題で悩む必要はないというメリットがあります。

#####鍵配送問題とは？
サーバとやり取りをするためには、サーバ側とクライアント側で鍵のやりとりをしなければなりません。
（厳密に言うと必ず必要というわけではないと私は思います。公開鍵認証ではなく、パスワード認証を用いる方法もあるからです。）

鍵のやり取りを行っている時点では、まだ暗号化されていないため、悪意のある人物が盗聴する可能性があります。
クライアント側「この共通鍵を使おうね」
サーヴァ側「分かりました」
悪い人「なるほどこの鍵を使えばサーバに入れるのか・・・＾＾」
ということになりかねません。
これが、鍵配送問題です。
鍵をやり取りする際に、その鍵がばれないように、もしくはばれても大丈夫なようにやりとりしなければなりません。

例えば共通鍵暗号方式を利用して、サーバとデータのやり取りをするとします。暗号化も復号も両方同じ鍵（**共通鍵**）を使ってやり取りをしているわけです。先ほどの悪意のある人がこのやり取りを見ていて、「さっき手に入れたこの共通鍵を使ってしまえば復号できるので、暗号化していてもやり取りしているデータ丸見えだぜ！」となってしまい、大変なことになります。
こういうことから、共通鍵暗号方式では鍵配送問題を解決するには工夫が必要なのです。
（アナログな方法では、紙に書いて郵便で送って、サーバに入れる人に鍵を設置してもらうだとか・・・打ち間違えそうですね）


**しかし、公開鍵暗号方式ではこの問題が解決できるのです！**

公開鍵暗号方式は、見られても大丈夫な公開鍵と、絶対に死守しなければならない秘密鍵を用いる方式です。
事前にサーバと鍵をやり取りする際に送る鍵は、この**見られても大丈夫な公開鍵**です。
悪意のある人物にこの公開鍵を盗聴されたとして、公開鍵によって暗号化されたデータを復号できるのは、それに対応する秘密鍵だけです。
鍵をやり取りするときも、データをやり取りするときも秘密鍵はネット上どこへも流れていません。
**見られても大丈夫な公開鍵を送るという方法**を使っているため、鍵配送問題は解決です！

**秘密鍵だけは絶対に誰にも教えてはいけません。秘密鍵をなくしてしまったり、盗まれたと分かった時点で、キーペアを作り直してください**

さて、２つの暗号化技術を頭の片隅に置いて話を進めていきたいと思います。

###SSHの仕組み
①公開鍵暗号方式（鍵交換）で「共通鍵」を共有すると同時に公開鍵暗号方式（電子署名）でホスト認証
②共通鍵暗号方式で暗号化通信開始
③ユーザ認証（パスワード認証、公開鍵認証等）

SSHは上記の手順でやり取りを行っています。
順に説明していきます。

####鍵交換とは？
鍵交換というのは、
1. クライアント側とサーバ側でキーペアを作り、互いに公開鍵を交換する。
2. その後、各自の持っている秘密鍵と組み合わせて計算を行います。
この２つの手順で鍵を共有する方式です。

クライアント側の秘密鍵とサーバ側の公開鍵　/　サーバ側の秘密鍵とクライアント側の公開鍵といった、互い違いになっている組み合わせから、同じ秘密情報が導き出されるそうです。
この秘密情報は共通鍵やセッションIDに活用できるそうです。

####電子署名とは？

電子署名でホスト認証をするというご指摘をいただきましたので、私なりに理解した電子署名についてまとめてみます。


電子署名には、
1. 電子文書が署名した本人が作成したことを証明
2. 電子文書が改ざんされていないことを証明
という２つの機能があります。

一体どうやって本人が作成したことと、改ざんされていないことを証明するのかを、私なりに理解したところまでまとめてみます。知識蓄積のためにも、ご指摘お待ちしております。

送信者側
電子文書をハッシュ関数に入れてハッシュ値を出し、認証局から取得した秘密鍵によりハッシュ値を暗号化します。
暗号化されていない平文の電子文書と、暗号化されたハッシュ値と送信者の公開鍵をまとめて電子署名といいます。

受信者側
電子署名を受け取った側は、平文の電子文書をハッシュ関数に入れてハッシュ値を出します。
その後、電子署名から公開鍵を取り出して、送られてきた暗号化されたハッシュ値を復号します。
受信者の出したハッシュ値と、送信者の送ってきたハッシュ値が一致していれば、その平文の電子文書は間違いなく本人が作成し、改ざんもされていないという証明になります。

ハッシュ関数には、同じ入力には必ず同じ出力をするという特徴があります。
仮にaaaという文字をハッシュ関数に入れれば、必ずhonyahonyaという（適当です）ハッシュ値が得られます。
ですので、今回の説明で行くと、受信者が送られてきた電子署名から取り出した電子文書をハッシュ関数に入れればhonyahonya（適当ですよ）というハッシュ値が得られ、かつ、暗号化されたハッシュ値を送信者の公開鍵で復号してhonyahonya（適当ですみません）となっているのであれば、電子文書を作ったのは送信者本人であり、改ざんはされていないという証明になるのです。
ここら辺は数学の世界っぽいですね・・・。数学不得意でまだまだ理解が及びません・・・。


####ホスト認証とは？
- クライアントが SSH サーバーに接続すると、最初に行われるもの。
- 接続しようとしているサーバーが正しいものであることをクライアントが検証するプロセス。

サーバに接続しようとした際
「このホストの公開鍵を信頼して接続しますか？」と聞かれたり、
「Are you sure you want to continue connecting (yes/no)?」と聞かれるあれです。

SSHで接続するたびにサーバ固有の公開鍵がサーバからクライアントに送られ、クライアント側で保存されているサーバの公開鍵と比較して一致するか確認しています。
known_hostsに公開鍵は保存されています。


ただし初回接続時はまだこの公開鍵を持っていないので比較ができません。
>「このホストの公開鍵を信頼して接続しますか？」と聞かれたり、
「Are you sure you want to continue connecting (yes/no)?」と聞かれるあれです。

ですので、こういったことを聞かれるのだと思います。
許可をすることでサーバの公開鍵を登録することができます。

２回目以降のサーバ接続時は、known_hostsファイルに保存されているサーバの公開鍵（指紋）と、サーバが送ってくるホスト認証鍵（公開鍵）を用いて、サーバの正当性をチェックし、信頼できるサーバかどうか判断させているのです。
仮に偽のサーバからホスト認証鍵が送られてきたとしても、known_hostsファイルにあるサーバの公開鍵とは異なるので、エラーが出ます。それによって、偽サーバに接続してしまうことを防ぐことができるのです。

#####ホスト認証のポイント
**偽のサーバ（ホスト）に接続してしまうことを防いでくれる**
二回目以降の接続なのに、上記の質問メッセージが来たときは注意してください。
違うサーバに接続しようとしている、もしくは接続させられそうになっている（なりすまし）可能性があります。
もちろんサーバを変更したということが分かっているのであればそのまま接続しても大丈夫だと思います。

本当に確認したい場合
- サーバ管理者に公開鍵（指紋）を確認してみる
- ~/.ssh/known_hosts　を確認する。警告メッセージが出て接続したくても接続ができない場合は、こちらに記載されているサーバの指紋を消してしまう、という手段もあると思います。消してしまえば、「このホストの公開鍵を信頼して接続しますか？」などの質問がされ、接続ができるようになると思います。


####ユーザ認証とは？
- パスワード認証
- 公開鍵認証

という主な２つの認証方式があります。

#####パスワード認証
パスワード認証とは、アカウントIDとパスワードで認証を行う方式です。
アカウントIDとパスワードさえわかればだれでも入ることができてしまいます。
最悪あるユーザーのふりをしてサーバに入られてしまい悪さをされる可能性があります。

パスワード認証を行っている時点では、暗号化された状態でネット上を流れていくわけですので、安全では・・・？ということにはなりません。
人が覚えることのできるパスワードはそこまで長くない、複雑なものでもないことが多いでしょう。
短いパスワードでは総当たり攻撃をされて突破されかねません。
紙に書いたり、定期的に変えればいいのでは？とも思いますが、その紙を誰かに見られたりなくしたら？定期的に変えるとなるとめんどくさくて簡単なパスワードにしてしまいがちでは？
と私は考えました。
上記のこともあり、個人的にパスワード認証はあまり好ましくないと思いました。

#####公開鍵認証
公開鍵認証とは、キーペアを利用する接続方法で、サーバーに公開鍵、クライアントに秘密鍵を置いて使用します。
RSAでの話になりますが、RSAで鍵を作る際は最低でも2048bit以上の鍵長で作ることをお勧めされているそうです。
2019年2月8日追記
ECDSAで鍵を作る場合は256bit以上が推奨されているそうです。


####公開鍵認証のおすすめポイント
**鍵を持っているクライアントのみが入ることができるのでパスワード認証より安全な点**
※PCごと紛失してしまった場合に備えて、秘密鍵自体にもパスフレーズを設定しておきましょう。鍵の作り方は別の方の記事を読んでみてください。

####通信自体の暗号化の仕組み

通信内容の暗号化・復号には**共通鍵暗号方式**が使われています。
毎回通信内容を暗号化する際に公開鍵暗号方式を使っていては処理が重くなってしまうので、共通鍵暗号方式を利用しているのです。
通信するたびにサーバが勝手に共通鍵を作ってくれているそうです。
共通鍵暗号方式には配送問題がありましたよね？
それを解決するには、~~公開鍵暗号方式~~**鍵交換**の出番です。

追記
SSHでは、公開鍵暗号は使わず、鍵交換（DH,ECDH）と、電子署名（RSA,DSA,ECDSA,EdDSA）を使うというご指摘をいただきました。
それを踏まえて共通鍵を交換するとはどういうことかまとめてみます。


#####公開鍵暗号方式で「共通鍵」を共有する場合

1. 犬さんと猫さんが公開鍵暗号方式を使って公開鍵を交換し、犬さんは猫さんの公開鍵を使って共通鍵の元となる乱数を暗号化し、猫さんに送る。
2. 猫さんは自分の秘密鍵で復号して乱数を得る。
3. この乱数が共通鍵となる機密情報となる。

この暗号化と復号の処理で機密性を実現しているのです。

>| 方式   |処理負荷の重さ |    配送問題 |
|:-----------------|:------------------|:------------------|
| 共通鍵暗号方式|シンプルな方式なのであまり負荷がかからない |  問題を解決するために工夫が必要  |
| 公開鍵暗号方式|仕組みが少々複雑なので負荷がかかる| 問題ない|


そういえば、公開鍵暗号方式は処理負荷がかかるというデメリットがあると前述していました。
確かに、通信は何度もなんども行われるのに、公開鍵暗号方式を使うのはおかしいですよね。

では、鍵交換で共通鍵を交換するとはどういうことかまとめていきます。
#####鍵交換で「共通鍵」を共有する場合
1. 互いにキーペアを作ります。
2. 公開鍵を交換します。
3. 交換後、各自相手の公開鍵と自身の秘密鍵を用いて鍵計算をする。
4. この計算結果が共通鍵として使える機密情報となる。

（こちらの方の記事に詳細が載っています。）
参考URL
https://qiita.com/angel_p_57/items/897bf94160be8d637585

公開鍵暗号方式よりも、鍵交換の方が負荷は少なく、
共通鍵を交換するということが目的であれば、鍵交換で十分である、ということです。

>①公開鍵暗号方式（鍵交換）で「共通鍵」を共有すると同時に公開鍵暗号方式（電子署名）でホスト認証

というように（鍵交換）を使ったのも、こういうことがありつけました。
SSHではそもそも公開鍵暗号方式は使わないというご指摘をいただき大変驚きました。

###SSHの仕組み
①鍵交換で「共通鍵」を共有と同時に電子署名でホスト認証
②共通鍵暗号方式で暗号化通信開始
③ユーザ認証（パスワード認証、公開鍵認証等）

結論SSHは上記の手順で行われているということが分かっていただければ幸いです。

##まとめ

SSHとは、暗号化や認証で、安全にリモートホスト間通信をするためのプロトコルであり、セキュアな状態でサーバに入ってリモート操作してくれる便利な子。

SSHは、
①鍵交換で「共通鍵」を共有と同時に電子署名でホスト認証
②共通鍵暗号方式で暗号化通信開始
③ユーザ認証（パスワード認証、公開鍵認証等）
の順番でやりとりをしています。

①に関して
２回目以降の接続なのにホスト認証で何らかのメッセージが出てしまったときは注意しましょう。

②に関して
通信内容の暗号化には共通鍵暗号方式を使っています。
その共通鍵を交換するには公開鍵暗号方式を使っています。
通信のたびに共通鍵をサーバが作ってくれます。

③に関して
ユーザ認証にはパスワード認証と公開鍵認証がありますが、公開鍵認証のほうが安全性が高いのでこちらがおすすめです。


###最後に
通信自体の暗号化には共通鍵暗号方式を使っているということは知らなかったので新たな発見でした。
また、電子署名を使ってホスト認証を使っているとのことも新たな学びでした。
LPICの本に出てくる、データ署名というのが電子署名なのか不明になってしまったため、そこは勉強しなおしたいです。
（もしデータ署名が電子署名と同義であるとすると、公開鍵認証時に電子署名によって本人確認をしている＝ユーザ認証ということになり、なるほど！と理解ができるのですが・・・。実際データ署名と電子署名の関係はどうなのでしょうか・・・。）
そして何より、SSHはそもそも公開鍵暗号方式は使わないというのが大変な驚きでした。


まだ勉強中でして間違っている部分がある可能性があります。
その際は、ここ違うよ、とコメントを頂けますと幸いです。


以上、SSHについて調べてみた、でした！