【図解】ブロック暗号の各モードについて，アルゴリズムとその特徴を少しだけ詳しく比較してみる（比較一覧表つき）

結城浩@hyukiさんの[『暗号技術入門 第3版』](https://www.amazon.co.jp/exec/obidos/ASIN/4797382228/hyuki-22/)をゼミで輪読していたのですが，ブロック暗号の各モードの違いについて，イマイチよく理解できていなかったので，改めて自分でまとめ直してみたいと思います．説明が足りない，間違っているなどありましたら，**どしどし** ご指摘ください！

記事の後半に大きめの画像が出てきますが，別タブで開くと見やすいです（PC推奨）

Noteは[こちら](https://note.mu/live_as_notes/n/nb61e9e8af2b9)

---



# 0.ブロック暗号【ぶろっくあんごう】とは？
- **共通鍵暗号**の一種：暗号化時・復号時に同じ鍵を使う．
- データを**固定長のブロック**に分けて暗号化する．
- 各ブロックを生成するアルゴリズムを**モード**という．

# 1.アルゴリズムを比べてみる

ブロック暗号の基本的なモードは5種類あり，それぞれECB・CBC・CFB・OFB・CTRモードと呼ばれます．まずは，これらのアルゴリズムについて1つ1つ見ていきましょう．

## **ECB**モード(Electric CodeBook mode)
[^ECB]平文ブロックを指定した長さで分割，切り出されたデータの長さが分割ブロック長より少ないときは，パティングで残りの分を埋めます．そのあと各ブロックごとに暗号化します．復号時はそれぞれのブロックを逆の手順で元に戻します．<br>
![image.png](https://qiita-image-store.s3.amazonaws.com/0/253921/e9a82a86-baec-6ef4-17a9-fa334723925f.png)<br>
性質上，複数の同じ内容のブロックを暗号化すると，それぞれ同じ内容の暗号化済みブロックが生まれるため，暗号化した状態でも，同じ内容のブロックの分布や出現確率などから全体の内容を推論しやすく，弱い暗号です．また，ブロックの前後を入れ替えたり別のデータと置き換えても，このアルゴリズム上では特にエラーが出ないので，改竄もしやすいという欠点があります．（他のアルゴリズムも同様ですが，改竄は，暗号化・復号アルゴリズムでは検知できないので，メッセージ認証コード(Message Authentication Code: MAC)を用いることで検知します．）※他と比べてかなり脆弱なアルゴリズムなので，相当な事情がない限りは使うべきではありません．

## **CBC**モード(Cipher Block Chaining mode)
[^CBC]チェーンのように，1つ前の暗号文ブロックと平文ブロックを，XORで連鎖させながら暗号化します．ただし最初の平文ブロックは，暗号文ブロックの代わりに「初期化ベクトル」(Initialization Vector)とのXORをとります．復号時は，復号した暗号文ブロックとその1つ前の暗号文ブロックとのXORをとります．<br>
![image.png](https://qiita-image-store.s3.amazonaws.com/0/253921/17dcdfa4-a8dd-c2ad-900f-6d023183c29c.png)<br>
『暗号技術入門』には書かれていませんでしたが，ブロック間のチェーンが隣同士のブロックに依存しているので，再生攻撃に弱いアルゴリズムでもあります[^HYUKI]．しかし，ECBモードの「繰り返しが見つけやすい」という欠点を克服していることや，CRYPTREC, Practical Cryptgraphyの推奨アルゴリズムであることから，信頼性は今のところ十分といえそうです．

20200511追記
cf. https://www.atmarkit.co.jp/ait/articles/2005/11/news017.html

## **CFB**モード(Cipher FeedBack mode)
[^CFB]1つ前の暗号文ブロックにさらに暗号化をかけたものを，平文ブロックとともに，XORへの入力として戻す（フィードバックする）ことで暗号化します．最初の平分ブロックは，初期化ベクトルに暗号化をかけたものとXORをとります．復号時は，平文ブロックと1つ前の暗号文ブロックを**暗号化**したものとのXORをとります．<br>
![image.png](https://qiita-image-store.s3.amazonaws.com/0/253921/84030393-dc4b-0895-e8c9-0b6b02ece59f.png)<br>
平文ブロックと暗号文ブロック（乱数の代わり）とのXORをとることで，使い捨てパッドのような仕組みを実現しているのが特徴です．[CBCモード](#CBCモード(Cipher-Block-Chaining-mode))のときに述べた「再生攻撃」によって，データがすり替えられやすいという弱点があります（下図）．<br>
![image.png](https://qiita-image-store.s3.amazonaws.com/0/253921/80f19f7c-928f-8283-2761-b56b2f2116d4.png)<br>

## **OFB**モード(Output-FeedBack mode)
[^OFB]初期化ベクトルを暗号化にかけて，そのアウトプットと平文ブロックとのXORで暗号文ブロックを作ります．復号は，アルゴリズムの入力・出力を入れ替えるだけで済みます．また，初期化ベクトルから鍵ストリームを先に生成しておくことで，暗号化・復号ともに並列処理ができるという特徴があります．<br>
![image.png](https://qiita-image-store.s3.amazonaws.com/0/253921/b399827e-d14e-b2d0-6913-69d99b60f580.png)<br>

## **CTR**モード(CounTeR mode)
[^CTR]初期化ベクトルの代わりに，ノンス（ランダムな値）と１ずつ増加していく連番を組み合わせたカウンタから鍵ストリームを生成し，平文ブロックとのXORをとることで暗号化します．復号時は，アルゴリズムの入力・出力を入れ替えるだけで済みます．<br>
![image.png](https://qiita-image-store.s3.amazonaws.com/0/253921/863da170-a720-279e-2000-84bd4183e78e.png)<br>
カウンタの前半「ノンス」は，リプレイ攻撃防止のため，毎回異なる値を用いますが，後半部分は生成したいブロックの連番からすぐに求められます．この性質おかげで，[OFBモード](#OFBモード(Output-FeedBack-mode))と違い，ノンスと連番さえ分かっていれば，順番を気にせず任意のブロックを暗号化・復号できます．簡易な設計ながら使い勝手が良く，CRYPTREC, Practical Cryptgraphy推奨なので，CTRモードは様々な場面に普及してきているようです．[^YCTR]

## アルゴリズム比較（一覧）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/253921/e653d12c-abb9-0218-2ee6-2f536878a2b4.png)


# 2.全体をざっくり比べてみる

各アルゴリズムについては何となく分かっていただけたと思いますが，正直なところ「個別に説明されても，頭に入ってきづらい」という人もいると思います（：僕のことです^^）．そこで，商品紹介ページによくある「機能比較表」っぽいものを作ってみました[^QMDC],[^AGN4]．（よく分からなかったところはハイフンを付けています．）
上下左右を見比べながら，各モードの違いについて確認してください．

![image.png](https://qiita-image-store.s3.amazonaws.com/0/253921/7c82044d-353c-fce0-d10c-fac99edacf3e.png)


パッと見たかんじでは，CTRがいちばん使い勝手が良さそうですね．CFBとOFBはYahoo!知恵袋のblanclux(仮)さん曰く，最近あんまり使われなくなってきており，CTRにとって代わられてきているようです．[^YCTR]

ちなみに，CFB,OFB,CTRでパティングがいらないのは，そもそも平文が直接的には暗号化アルゴリズムに通されていないおかげです．またOFBとCTRでは，前後の平文・暗号文ブロックが直接連鎖させられていない（それぞれが分離されている）ので，XORするときに使う値（連鎖的に暗号化された文字列or連番）を，平文・暗号文のどちらにも依存せず生成できます．つまり，暗号化・復号する際にデータが揃っていなくても，XORの手前までの作業を並行して行ったり，事前に終わらせておくことができるというメリットもあるのです．



# 3.使い分けを考えてみる．

ここが一番気になるところとも言えますが，なかなか情報が見つからないので，そのうち別記事で書こうと思います．もし「こんな事例あるよ」というのがあれば，ぜひ教えてください！

# 4.よくわかってない部分
- **CTSモード（パティングの処理）[^CTS]の仕組みについて**
　フローは書いてある通りのを理解すればいいんだろうけれど，なぜブロックの入れ替えをするのか，どうしてそれでうまくいくのか...？

- **CFBモードは何故1ビットずつ暗号化できるのか[^CFB1b]**
　というか，CFBモードじゃないとできないことなのか？「平文-暗号文の間がXORだけだから」という理由なら，OFBやCTRも1ビットずつ暗号化・復号できるのでは？

- **「暗号化の途中でモードを切り替えることはできないか」という質問について**
　授業中に上記のようなトリッキーな提案?がありました．CTSモードのことを考えると，できなくはなさそうだと思うのですが，逆に脆弱性増えそうな気もしますし，アルゴリズムを外部に晒す以上は殆ど無意味な気しかしないのですが，...どうなんでしょう？


# 5.おまけ
読んでおくとためになるかも？

- [security etc...「Padding Oracle AttackによるCBC modeの暗号文解読と改ざん」](http://rintaro.hateblo.jp/entry/2017/12/31/174327)

>... **パディングオラクル攻撃**を用いると、鍵を持っていないにも関わらず暗号文を解読できてしまうとよく言われるが、実は**同じ仕組みを用いることで**暗号文の**改ざんも**行うことができる。...

- [第4回暗号勉強会 スライド](https://docs.google.com/presentation/d/1xxAtkuP3s_OysDWxLaMDOZQLn-0dfTqXiPnTpM3Gvsg/edit#slide=id.g384e492e2_055)

>... **JavaのCipherクラスのデフォルト実装はECBモード**なので何も考えずに使うと脆弱な暗号を使ってしまうので注意! ...

- [クラウドサービスに最適な暗号方式とは？――暗号化したまま計算する「準同型暗号」](http://www.atmarkit.co.jp/ait/articles/1508/14/news001.html)

>... 準同型暗号を使うと、クラウド上で**暗号化したまま統計処理**を行い、そのまま**暗号化された結果だけを取得**できます。あとはクライアントで復号するだけでよいのです。...

[^AGN4]: 『暗号技術入門 第3版』第4章 pp.81-110（章全体）
[^ECB]: 『暗号技術入門 第3版』第4章 pp.85-88 ECBモード
[^CBC]: 『暗号技術入門 第3版』第4章 pp.89-95 CBCモード
[^CTS]: 『暗号技術入門 第3版』第4章pp.95-96 CTSモード
[^CFB]: 『暗号技術入門 第3版』第4章 pp.97-100 CFBモード
[^CFB1b]: 『暗号技術入門 第3版』第4章 pp.99 CFBモードとストリーム暗号 下から2行目
[^OFB]: 『暗号技術入門 第3版』第4章 pp.101-103 OFBモード
[^CTR]: 『暗号技術入門 第3版』第4章 pp.103-106 CTRモード
[^QMDC]:  [「共通鍵暗号の暗号モード CTRについて」暗号モードの特徴一覧](https://qiita.com/asksaito/items/130863fe9e6a08dcd65d#%E6%9A%97%E5%8F%B7%E3%83%A2%E3%83%BC%E3%83%89%E3%81%AE%E7%89%B9%E5%BE%B4%E4%B8%80%E8%A6%A7)
[^YCTR]: [Yahoo!知恵袋「ブロック暗号のモードについての質問です。」](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q10160484730)
[^HYUKI]: https://twitter.com/hyuki/status/39428350858629121