そろそろ暗号方式やらデジタル署名やらを理解する

ソフトウェアエンジニア歴そろそろ1年だしまとめる。


# 暗号方式２種類

## (1)秘密鍵(共通鍵)暗号方式

- HS256 (HMAC with SHA-256)はそのアルゴリズムの一つ(?)
    - クライアント側とサーバー側が共通のSecretKeyを持つ。
- JWT, HTTPS通信の実際のやり取りで使われる

- 公開鍵暗号方式より高速(1/1000)で暗号化、復号の処理ができると言われている。

## (2)公開鍵暗号方式

- 非対称アルゴリズム(公開鍵と秘密鍵を使用)
- 実現したいのは「公開鍵で暗号化したものが秘密鍵を持つ人間にしか復号できない」こと
    - このため、キーペアを発行するのはメッセージの受信者。

- [公開鍵暗号方式の中で「秘密鍵で暗号化、公開鍵で復元」(通常と真逆)ということができるのはRSA方式のみであり、他の公開鍵方式では不可能](https://qiita.com/angel_p_57/items/d7ffb9ec13b4dde3357d)
- JWT, デジタル署名、SSH接続、HTTPSの接続の確率に使われる

# 暗号化を用いた技術

## デジタル署名(2を使用)

- [公開鍵暗号方式を使って実現した電子署名がデジタル署名](https://wa3.i-3-i.info/diff268hanko.html)らしい。
- アルゴリズムは、ハッシュ関数と公開鍵暗号方式を組み合わせたものである。
- 担保したいのは以下の二つ
    - `本人照明(そのメッセージが本当にAによるものか)`
    - `非改竄証明(そのメッセージが改竄されていないか)`
- このためペアキーを発行するのはメッセージの発行者。
    - なお繰り返しになるが、[公開鍵暗号方式の中で「秘密鍵で暗号化、公開鍵で復元」ということができるのはRSA方式のみであり、他の公開鍵方式では不可能](https://qiita.com/angel_p_57/items/d7ffb9ec13b4dde3357d)

1. 送信者Aは秘密鍵と公開鍵を作成し、公開鍵を受信者Bさんに渡す。
3. 送信者側は「伝えたいメッセージ」と「その署名(メッセージをハッシュ化して、秘密鍵で暗号化した暗号文)」を両方送信する。
4. 受信者側は`「メッセージ」をハッシュ化したもの`と`署名を暗号鍵で復号したもの`が同一であるかを確認することによって署名が信頼できるものかを確認する。



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/f487391e-9ec3-e5ae-36d1-a9b07f4e17fa.png)
[画像](https://www.ipa.go.jp/security/pki/024.html)




## JWT(1or2を使用)

`JWT = ヘッダー + ペイロード + 署名`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/0c9030d0-86a4-2852-8254-70d0a846b592.png)
[画像](https://ja.wikipedia.org/wiki/JSON_Web_Token)

- 署名の作り方は以下の２通り。
    - RS256(公開鍵+秘密鍵を使うやつ)
    - HS256(Secret Keyを使うやつ)

- JWS (JSON Web Signature)は、ザックリ言うと「JSONに電子署名をして、URL-safeな文字列として表現したもの」です。参考までに、JWE (JSON Web Encryption)は「JSONを暗号化して、URL-safeな文字列として表現したもの」です。



## HTTPS通信(1→2を使用)

### (1)クライアント側で作った共通鍵をサーバに送るまで([ディフィー・ヘルマン鍵共有](https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%A3%E3%83%95%E3%82%A3%E3%83%BC%E3%83%BB%E3%83%98%E3%83%AB%E3%83%9E%E3%83%B3%E9%8D%B5%E5%85%B1%E6%9C%89))

- サーバとクライアントの両方が(ある程度ルールを示し合わせた上で)各々公開鍵と秘密鍵を発行し、公開鍵のみを相手に送信し、各自、自分の秘密鍵と受信した公開鍵から(同一の!)共通鍵を作成できる方法である。
- 第三者が送受信されるデータ（すなわち、二人の公開鍵）を盗聴しても鍵を生成することができない所に特徴がある。


**[補足]**
なお昔は[この](https://www.infraexpert.com/study/security4.html)様に通信していたが、TLS v1.3 では RSA 公開鍵による共通鍵生成方式は廃止になりました。
1. サーバでRSAキーペアを作り、公開鍵をクライアントに送信する(ちなみに、デジタル証明書も一緒に送信される)
2. クライアントは共有鍵を作成し、それを公開鍵で暗号化してサーバに送信する
3. サーバでは秘密鍵を用いて、受信した公開鍵を復号する



### (2)サーバとクライアント間の共通鍵の交換後
- 共通鍵を用いて通信内容を暗号化/復号する。

- [Webサイトの証明書に含まれる「公開鍵」は、その後の「共通鍵」を交換するための手段として使われ、直接的にデータを暗号化するのには使われません。実際の暗号化に「公開鍵暗号」を使うのでは無く、その場で作成された「共通鍵」を使用するのは、共通の秘密鍵をその場で作成して暗号化に使い、通信完了後に鍵を破棄すればより、片割れが常にネットに公開されている「公開鍵」と違いまったく暗号の手がかりが残らず、暗号としてより強固になる。というメリットがあるためです。ここでは、現実世界のディーテイルについては、脇に置いておいて単純化された「公開鍵暗号」システムを考えます。](https://www.engineer-memo.net/20180804-4724)



### SSLサーバー証明書を発行する手順

1. サーバはSSLサーバ証明書をサーバーにインストールする必要がある。
1. サーバー運用者が認証局CAに申請し、身分確認後、(認証局の秘密鍵で暗号化された)SSL証明書をサーバーに渡す。
2. ウェブサイトの運営者が正しい運営者かの審査ののちに発行される
    - DNSでFQDNから発行されたIPアドレスをもとにサーバーにアクセスしてきたクライアントに対して、`確かにそのIPアドレスは君がアクセスしようとしているFQDNです`ということを証明する。
    - この中で秘密鍵暗号方式が使用されている。またいつか調べる。
    
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/f9520fbc-0185-6bcc-21fc-920d21ccf990.png)
[画像](https://milestone-of-se.nesuke.com/sv-advanced/digicert/digital-certification-summary/)




## [SSH通信](https://l-w-i.net/t/openssh/auth_001.txt)

### (1)パスワード認証方式


### (2)公開鍵認証方式(2を使用)


- 公開鍵認証方式で、クライアントがキーペアを発行し、サーバー側に公開鍵を保存しておく。
    - デジタル署名と同形式

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534442/e3580d98-6a5e-544d-769b-d1dcf93735cf.png)
[画像](https://www.kagoya.jp/howto/rentalserver/ssh/)