暗号技術まとめノート

# ハッシュ
あるデータから決まった長さのデータを算出するアルゴリズム。  
下記の特徴を持つ。
1. 算出結果は意味を持たない（文字の羅列のような）データとなる。
2. 元のデータが同じであれば、算出結果は必ず同じデータになる。
3. 元のデータが少しでも異なれば、算出結果のデータは全く異なる値となる。
4. 算出結果のデータから元のデータを逆算することは困難。

ハッシュの算出結果をそのまま「ハッシュ値」と言う。

世に普及しているハッシュの計算方式（アルゴリズム）は複数存在する。
SHA1、SHA256、SHA384、SHA512、MD5 等...
元のデータが同じでも、ハッシュのアルゴリズムが違えば算出結果は異なるデータとなる。

ハッシュ値は元のデータの暗号化に利用したり(1の特徴)、元のデータに付与する識別子（2,3の特徴）として利用することができる。識別子としてのハッシュ値は「メッセージダイジェスト」と呼ぶことがある。

また、1～4の特徴を全て利用する形で、一般的なWebサービスのユーザーのパスワードはハッシュ値でサービス側のデータストアに保存されている（諸説あり）。

機密情報をハッシュ値で保存する場合、ハッシュの種類が判明すると元の値を推測しようとする人が現れるため、ハッシュの種類や計算方式は公開しない方がよい。

ハッシュ値は後述する「署名」を作る際にも利用される。署名とはあるデータを送る際に通信経路で改ざんされているかどうかを検知するためのデータで、送り主が元のデータのハッシュ値を暗号化して作成する。署名は元のデータと一緒に宛先に送られる。

## 例
rubyにはdigestというライブラリがあり、文字列データからSHA1、SHA256、SHA384、SHA512、MD5のハッシュ値を算出できる。

「pancakeoishii」という文字列のハッシュ値(16進数表記)は以下の通り。
```
irb(main):001> require 'digest'
=> true
irb(main):002> Digest::SHA1.new.update("pancakeoishii").hexdigest
=> "a5756cff0ac4456b66f7aa43e8860a5b437b9ff0"
irb(main):004> Digest::SHA256.new.update("pancakeoishii").hexdigest
=> "f95fbc176def5f4c3b454ffdae12a54827f17bc643eacc7f4fae57f56adb7b40"
irb(main):005> Digest::SHA384.new.update("pancakeoishii").hexdigest
=> "776349ee053f7cc6d3787bd0f85f02f0b49baef8cf6e5e9f9441de85b81260dd3f9ecb4dd53b9e549602789c322fbf3a"
irb(main):006> Digest::SHA512.new.update("pancakeoishii").hexdigest
=> "23c209059780dbda0ff44bb95181f398bd515a9aa4c6c0ed9771f5c295acb617bc4a62cc3d61a0d3b7c93c51416b77f6744cffe1f73725022de725f436e9001c"
irb(main):007> Digest::MD5.new.update("pancakeoishii").hexdigest
=> "4ecc7dab5e47746838d041e477e6f6e0"
irb(main):008>
```
他のハッシュ計算ツールで「pancakeoishii」という文字列のハッシュ値を計算すると、同じ値が算出されることが確認できるだろう。

# 暗号化通信
通信でデータをやり取りする時に、第三者にデータの中身が傍受されないように、鍵を使ってデータを暗号化および復号化すること。

鍵とは、あるデータを暗号化 or 復号化するのに必要なこれまたデータ（値）である。
ここでは、鍵（という値）を使ってデータを暗号化 or 復号化するための具体的なアルゴリズムについては言及しない。

代表的な暗号化通信方式は共通鍵暗号と公開鍵暗号である。

## 共通鍵暗号
あるデータに対して、1つの鍵で暗号化と復号化を行う方式。
この方式では自分と通信相手が予め同じ鍵を持っておく必要がある。
即ち、

![スクリーンショット 2024-09-06 233858.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985939/0a5af77c-cbba-3568-fcbc-90eddfc5048e.png)

共通鍵暗号方式では、作成した共通鍵が第三者の手に渡らないように注意して管理する必要がある。
1度共通鍵が漏洩すると、その鍵を使って暗号化したメッセージは第三者に複合化されてしまう可能性があるためである。
また、上記の性質上、同じ共通鍵は1人の通信相手としか使えない。逆に言えば、やり取りする相手毎に異なる共通鍵を用意する必要がある。

## 公開鍵暗号
あるデータに対して、2つの鍵で暗号化と復号化を行う方式。
2つの鍵とは、「公開鍵」と「秘密鍵」のペアである。

このペア（要は鍵という値の組み合わせ）は以下の性質を持つ。
1. 一方の鍵で暗号化したデータは、他方の鍵でのみ複合化することができる。
2. ペアの一方の鍵から他方の鍵の値を推測することは困難。

従って、鍵のペアの片方を自分だけが持っておく「秘密鍵」、他方を通信相手に共有する「公開鍵」として分けて、以下のような暗号化通信を行う。

1. 暗号化通信を行いたい者が、公開鍵と秘密鍵のペアを作成する。秘密鍵は自分以外に漏洩しないように厳重に管理する。
2. 暗号化通信を行いたい者が、公開鍵を通信相手に配布する。（公開鍵は、第三者の手に渡っても問題ない）
3. 通信相手は公開鍵を使ってデータを暗号化する。
4. 通信相手は暗号化したデータを秘密鍵の持ち主に送る。
5. 秘密鍵の持ち主は、公開鍵を使って暗号化されたデータを、自分だけが持っている秘密鍵を使って複合する

公開鍵暗号方式では、不特定多数の者が公開鍵を使って送りたいデータを暗号化することが出来る。
逆に、公開鍵を使って暗号化されたデータの複合化は秘密鍵を持っている者にしか行えない。
従って、秘密鍵さえ漏洩しなければ、安全に暗号化したデータを送ることができる。

また、暗号化通信を行う二者間で暗号化したデータを双方に送りたい場合は、それぞれが公開鍵と秘密鍵のペアを作成し、お互いに公開鍵を配布しあえばよい。Aさんに暗号化したデータを送るには「Aさんの公開鍵」を使う、Bさんに暗号化したデータを送るには「Bさんの公開鍵」を使う…といった感じである。

# 署名
データを送る際、そのデータが通信経路上で改ざんされていないことを確認するためのデータ。また、データの送り主のなりすましを検知することも可能である。
元のデータのハッシュ値を、更に暗号鍵を使って暗号化したものが「署名」である。
元のデータはメッセージと言ったりする。

メッセージの送信者は、メッセージから署名を作成し、メッセージと署名の両方を宛先へ送る。
メッセージと署名を受け取ったものは、署名を使ってメッセージが改ざんされていないことを確認する。

## 例
公開鍵暗号方式を使って署名による改ざん検知を行う方法の例。

1. 送信者は秘密鍵と公開鍵のペアを作成し、公開鍵を受信者に配布しておく。
2. 送信者はメッセージのハッシュ値を算出し・・・ハッシュ値A、さらに秘密鍵で暗号化する。（署名の作成）
3. 送信者はメッセージと2.で作成した署名を受信者へ送る。
4. 受信者はメッセージとその署名を受け取る。
5. 受信者はメッセージからハッシュ値を算出する。　・・・ハッシュ値B
6. 受信者は公開鍵を使って署名を複合化し※1、中身のハッシュ値Aを取り出す。
7. 受信者はハッシュ値Aとハッシュ値Bが一致することを確認する。ハッシュ値が一致すれば改ざんされていない。

攻撃者がメッセージを改変した場合、ハッシュ値Bは全く異なる値となり、7.でハッシュ値は一致しない。
攻撃者がメッセージを改変して署名も独自に作成（なりすまし）しても、攻撃者は秘密鍵を持っていないので、受信者は6.で公開鍵を使って正しく複合化できない。

従って、署名を複合化して検証する過程でメッセージの改ざんとなりすましを検知することができる。

※1公開鍵暗号方式の鍵ペアの性質を思い出してみよう。

# インターネット
インターネットによる通信は、不特定多数のユーザーが利用する公衆のネットワークで行われる。
そのため、通信相手がなりすましていたり、通信内容が窃取されるリスクがある。
このようなリスクを回避するために、暗号技術が使われている。

## トンネル
インターネットにおいて、仮想的に二者間の専用通信路を作る技術。
通信相手のなりすましと通信内容の窃取を防ぐ。

通信相手を認証し、通信内容を暗号化して送ることがトンネルを作った状態である。
トンネルを利用する通信プロトコルとして、TLS/SSL, IPsec等がある。

### 通信相手の認証
**電子証明書**によって認証する。
電子証明書で通信相手を認証することによって、偽の通信相手（なりすまし）と接続してしまうことを防ぐ。

### 通信内容の暗号化
電子証明書を利用して、通信内容を暗号化するための鍵交換も行う。

#### 例1：WebサーバーとTLS/SSLを使って安全に通信する。
TLS/SSLはトンネルを利用する通信プロトコルである。
共通鍵暗号方式によって通信内容を暗号化する。また、共通鍵の受け渡しは公開鍵暗号方式によって行う。このように共通鍵暗号と公開鍵暗号を組み合わせた暗号化通信をハイブリッド暗号方式と言ったりする。

##### Webサーバー側がTLS/SSLプロトコルに対応する
Webサーバーが認証局によって発行された電子証明書を登録すると、TLS/SSLに対応することができる。

①Webサーバー管理者が公開鍵と秘密鍵のペアを作成する

②電子証明書を登録する。
TLS/SSLにおける電子証明書は「TLS/SSLサーバー証明書」である。以下、短くしてサーバー証明書という。サーバー証明書は`認証局(CA Certificate Authority)`という機関に発行してもらう必要がある。

認証局はWebサーバーの信頼性を保証する機関であり、審査によってWebサーバーが信頼できることを確認した後、対象のWebサーバーにサーバー証明書を発行する。要はインターネットにおいてTLS/SSLによる安全な通信は認証局の存在によって成り立っている。

Webサーバーの管理者は①で作成した鍵ペアを認証局に送ってサーバー証明書の発行を依頼する。
認証局は対象のWebサーバーに対して審査を行い、審査通過すればその正当性を保証するものとしてサーバー証明書を発行し、対象のWebサーバーの管理者へ送付する。

Webサーバー管理者はWebサーバーへサーバー証明書を登録する。これでWebサーバーはTLS/SSLプロトコルに対応した状態となる。

③サーバー証明書の内容
1. Webサーバーの諸情報
2. ①で作成した公開鍵
3. 1と2のデータのハッシュ値を、認証局だけが持つ秘密鍵で暗号化した「署名」