超入門暗号セキュリティ１

# はじめに
暗号って単純です！
自分の復習をかねて、簡単な暗号の紹介から、暗号学者の道具箱と呼ばれる用語の説明までをします

# もくじ
[そもそも暗号とは](#そもそも暗号とは)
[身近な暗号](#身近な暗号)
[もう少し実用的な暗号](#もう少し実用的な暗号)
[用語](#用語)

# そもそも暗号とは

暗号とは、知ってる人だけで情報のやり取りをする技術です。
解読方法を知っている人だけがやり取りの内容を知ることができます。

#  身近な暗号

### 合い言葉
「ひらけゴマ」「山、川」みたいなやつです。
秘密の言葉を使って仲間かどうかを判別しました。
私はこれを最古の暗号だと思っています。

### スラング・略語
見方によってはこれも暗号です。
ネットスラングやJK用語など、意味を知っている人とは意思の疎通ができます。
長いJK用語は本当に使っている人いるのかしら...

### あいうえお作文
暗号技術的に言うと、スガノグラフィといいます。
語句の頭文字を集めると他の語句が出てくるやつです。
うっかりしていると見逃しちゃうので、気がつけると嬉しいですよね！

----
さて、意図的に暗号らしくないものを選んで紹介しました。
暗号と聞くと難しく考えちゃうかもしれませんが実際は単純なものです。
知ってる人だけで情報をやり取りできればそれは暗号です！

# もう少し実用的な暗号
続いて、もう少し実用的な暗号をクイズ形式で紹介します。


### 例1
次の変換の法則はなんでしょう？
`qiita -> rjjub`
`ango -> bohp`

<details><summary>答え (この行をクリックで開きます)</summary>
*アルファベットを一文字進めています。*
*a->b, c->d という変換です。*
</details>

これはシーザー暗号と呼ばれるものです。
古代ローマのジュリアス・シーザーが使ったといわれているためこの名前が付きました。
「ブルータス、お前もか。」で有名な彼で、紀元前100年ごろの暗号になります。


### 例2
次の変換の法則はなんでしょう？
`3 -> 0`
`4 -> 7`
`5 -> 6`

<details><summary>答え (この行をクリックで開きます)</summary>
*3との排他的論理和(XOR)です*
3 ⊕ 3 = 0
4 ⊕ 3 = 7
5 ⊕ 3 = 6
</details>

これはXOR暗号と呼ばれるものです。
XORは整数のswapを一行でできるので個人的に好きです (C++だけ?)
誰にも解読できない「使い捨てパッド」という最強の暗号に使われる仕組みです。

----
数字が出てきて暗号っぽくなってきました。
実は、インターネット上で使われる暗号は数字によるものです。
そうすることでパソコンで扱えて、安全性も数学により論理的に証明できます。

文字コードを使えば文字を数字に変換できるので、そのようにして使用しています。
ASCII、Shift-JIS、utf-8とかいうあれのことです。



# 用語
最後に暗号用語を紹介します！

## 超基本
・平文：伝えたい情報
・暗号：暗号化された情報
・暗号化：平文を一目ではわからなくすること
・復号：暗号を平文に戻すこと
・鍵：暗号化の時に使ったヒント

<details><summary>例1 で言うと...</summary>
・平文：`qiita`
・暗号：`rjjub`
・暗号化：文字を進めること
・復号：文字を戻すこと
・鍵：`1` (ずらす量)
</details>

<details><summary>例2 で言うと...</summary>
・平文：`3`
・暗号：`0`
・暗号化：XORを計算すること
・復号：XORを計算すること
・鍵：`3` (XORを計算する値)
</details>


## 共通鍵暗号 (対称暗号、秘密鍵暗号)
例1 と 例2 の暗号には共通点があります。
それは、暗号化と復号で鍵が同じという点です。

暗号化と復号で鍵が同じ暗号を共通鍵暗号といい、AES (Rijndeal), DES などがあります。
処理が高速なのが特徴です。


#### 鍵配送問題
共通鍵暗号を使うときに出てくる大きな問題です。

例えば、ログイン時のパスワードやクレカの情報などが漏れたら大変ですよね...
そのためこれらの情報は暗号を使って使ってやり取りをします。
ただ、クレカ会社などに前もって会うことはできないので、鍵を共有できません。
ネット経由で必要があります。

でも、通信傍受されているかもしれない状況では鍵を送れませんよね。ばれちゃうので...

という問題です。


## 公開鍵暗号
公開鍵暗号は鍵配送問題に対応できる暗号方式です。
(公開鍵のすり替えなど、いくつか問題は残ります)

公開鍵暗号には公開鍵とプライベート鍵の二つの鍵があり、公開鍵で暗号化、プライベート鍵で復号ができます。
さらに、公開鍵を全世界に公開し、プライベート鍵は自分だけが知る状態にします。

こうすることで、公開鍵により誰もが暗号を作ることができます。
また、公開鍵は暗号化のみで復号はできないので、プライベート鍵を持っている自分だけが読むことのできるメッセージになります。

鍵配送問題で書いた例で言うと、クレカ会社の公開する公開鍵を使って暗号化すれば、クレカ会社だけが情報を知ることができます。
暗号化した暗号はプライベート鍵がないと復号できないので、通信内容を他の誰かに知られても問題ありません。

かの有名なRSA暗号や、webプロトコルのSSL/TLSで使われるDH鍵交換などにこの方式が使われています。

共通鍵暗号に比べて処理が遅く、状況に合わせて共通鍵暗号と組み合わせて使われます。
数学により安全性が担保されています。
(正確には、ミレニアム問題の「P≠NP予想」が成り立った場合に安全性が保障されます)


## 一方向ハッシュ関数
メッセージ(入力)に対してハッシュ値と呼ばれる固定長の値を出力する関数です。
次の特性があります。
・メッセージのサイズはどれだけ大きくても関係ない
・メッセージが1bitでもずれるとハッシュ値は大きく変わる
・メッセージとハッシュ値から、同じハッシュ値を持つ別のメッセージを見つけることが難しい (弱衝突耐性)
・ハッシュ値が一致した2つのメッセージを見つけることが難しい (強衝突耐性)
・ハッシュ値から元のメッセージに戻すのが難しい (一方向性)

ファイルが1bitでも変わるとハッシュ値が大きく変わるので、ファイルの書き換わりを検出できます。

この特性から、サイトからダウンロードしたファイルが元のサイトと同じ物か検証ができます。
例えば、[Ubunts18.04.3](http://releases.ubuntu.com/18.04.3/) のリリースノートにもハッシュ値の計算結果があります。
`MD5SUMS`や`SHA1SUMS`などが計算結果です。

手元で計算したハッシュ値を比べて、一致していれば元のファイルと同じだといえます。

----
※プログラミングで使う「ハッシュマップ」とは別物です。
暗号の分野でハッシュと言われたら「一方向ハッシュ関数」のことを指すのでご注意ください。

----

## メッセージ認証コード
「相手」と「メッセージの内容」が正しいものかを保証する技術です。

メッセージ認証コードは関数で、送信者と受信者だけが共有している鍵とメッセージを混ぜ合わせ、ハッシュ値を計算するものです。

「相手」と「メッセージの内容」が正しければ、鍵とメッセージを混ぜ合わせたものが自分と相手とで一致します。
そのため、そこから計算したハッシュ値 (MAC値)も一致します。

MAC値が違っているときは、通信中のエラー・改ざん・なりすましが検出されたときです。

ただ、送信者と受信者が同じ鍵を共有していることが前提なので、先ほどの鍵配送問題がでてきます。


## デジタル署名
デジタル署名は、第3者に対して、誰が書いたメッセージかを証明する技術です。
気密性を守るための技術ではないことに注意です。

相手が正しいかの証明はメッセージ認証コードを使えばできるのですが、一対一の状況での話です。
第3者への証明はできません。

なぜなら、お互いに鍵を共有する必要があるからです。

...ここで出てくるのが公開鍵暗号と似た考え方です。
公開鍵暗号は二つの鍵を使い、公開鍵で暗号化し、プライベート鍵で復号しました。

デジタル署名も二つの鍵を使うのですが、それとは逆の操作になります。
つまり、プライベート鍵で暗号化し、公開鍵で復号するのです。

具体的には、特定の文字列 (平文)をプライベート鍵で暗号化し、「暗号文・公開鍵・平文」を公開します。
公開鍵で復号し、公開した平文と一致すればプライベート鍵を持っているということになります。
それはつまり、暗号文の作成者だという証明になります。

公開鍵で復号できる暗号を作れるのは、プライベート鍵を持っている人だけなので、こう言えるのですね。


## 疑似乱数生成期
乱数といえば聞いたことあるんじゃないでしょうか。
無作為に選ばれた数字のことです。

暗号技術で使われる乱数は他の分野とは少し意味が違い、次の3要素を持っています。
・生成される数字に偏りがない (無作為性)
・これまでに出た数字から次に来る数字を予測できない (予測不可能性)
・ある乱数列と同じ数列を再現ることはできない (再現不可能性)

ソフトウェアで作る乱数はすべて周期をもって繰り返し生成されるため真の乱数とは言えません (だから"疑似"乱数生成器)
真の乱数はアナログな情報から作るのが正しいです。
実際には、そのときの[ハードウェアの温度](https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%BC%E3%83%89%E3%82%A6%E3%82%A7%E3%82%A2%E4%B9%B1%E6%95%B0%E7%94%9F%E6%88%90%E5%99%A8)をもとに作っていたりします。