暗号化/ハッシュ化について調べた


何もできなかったから過去書いたネタを転載(ぉ

暗号化アルゴリズム

暗号化と複合

暗号化は誰でもアクセス可能なパブリックな場所でデータを転送する際に、第三者にデータを盗み見されたり、改ざんされないようにデータを守るために用いられる。

暗号化や複合は、暗号化アルゴリズムと鍵によって行われる。

2種類の暗号化方式

暗号化アルゴリズムには大きく分けて2種類のものがある。

  • 共通鍵暗号
  • 公開鍵暗号

共通鍵暗号

この方式は、直観的に理解しやすい。

いわゆる現実で用いる「鍵」と同様の方法で、一つの「鍵」を用いて鍵をかける(暗号化)ことができ、さらに同じ「鍵」で鍵を開ける(複合化)できる。

また、この「鍵」を「共通鍵」と呼ぶ。

欠点と相手は、暗号化する側と、複合化する側が異なる場合に同一の「共通鍵」をそれぞれが保有している必要がある。

これは、「共通鍵」を他人が知り得てしまった場合は、その他人が暗号文を解読できてしまうというリスクが発生する。

公開鍵方式

この方式は、少し現実で表現しにくい。

二つの鍵を用意し、それぞれ、「暗号化用」と「複合化用」とする。

「暗号化用」の鍵を「公開鍵」と呼び、「複合化用」の鍵を「秘密鍵」と呼ぶ。

使用するときは、複合化する側が2つの鍵を生成し、「公開鍵」を暗号化する側に渡す。

渡された暗号化する側が「公開鍵」で暗号化を行った後、複合化する側に暗号文を渡す。

複合化する側は「秘密鍵」を用いて暗号文を複合化できる。

この方式の特徴は、「公開鍵」で暗号化したものは「秘密鍵」でのみ複合化できるということで、かつ、「公開鍵」を用いて「秘密鍵」を推測することができないことである。

「公開鍵」を知り得ても暗号化はできても複合化ができないため、必ず「秘密鍵」を持っているものしか暗号文を解読することはできない。

欠点としては、共通鍵方式と比べると処理(暗号化・複合化)の速度が遅い。

ハイブリット方式

それぞれの方式には利点・欠点がありそれを補完するためにはブリット方式が存在する。

ハイブリット方式では、データの暗号化には「共通鍵方式」を用い、この「共通鍵」を受け渡す際に「公開鍵方式」で暗号化を行うというものである。

「共通鍵」の漏えいリスクを「公開鍵方式」で担保し、高速な「共通鍵方式」のアルゴリズムでデータを担保するという手法。

共通鍵方式の中での2種類の方式

共通鍵方式の中で、その手法を大きく2つに分けることができる。

それが以下の2つの種類の暗号化方式である。

  • ブロック暗号
  • ストリーム暗号

ブロック暗号

ブロック暗号は、暗号化対象の平文データを一定の長さのブロックに分割して暗号化を行う手法である。

通常、平文データは1byte単位の可変長であるが、1byteごとに1byteの暗号文としていた場合は256通りのパターンでしかないため、簡単に解読されてしまう。

これを防ぐために、8byte(64bit)や、32byte(256bit)といった、より大きな「ブロック」ごとにまとめて暗号化する方式で解読を難しくしている。

ストリーム暗号

ブロック暗号では、ブロック毎に暗号化をすることで1byte毎の暗号化よりも解読を難しくしているが、結局ブロック長が短ければパターン数が少なく解読の難易度も下がってしまう問題は変わらない。

ブロック長を十分な長さにしたとしても、過去あった暗号化方式であるDESでも起こったように、コンピュータの性能向上によって脆弱なアルゴリズムになってしまう。

そこで、任意長の鍵ストリーム列を生成させ、これと入力の平文を演算させる「ストリーム暗号」が考え出された。

これは、1bitや1byte単位でデータを暗号化でき、かつ、パターンを十分に増やせる。

また、対象の平文の長さを気にしなくて済むため、SSL(HTTPS)や無線LAN(WEP)など、ネットワークトラフィックを暗号化するために利用されている。

暗号化アルゴリズムの種類

暗号化アルゴリズム一覧

# 方式 暗号化方式 暗号アルゴリズム 信頼度 規格 備考
1 共通鍵 ブロック DES RFC 2451
2 共通鍵 ブロック AES
3 共通鍵 ブロック Rijndael
4 共通鍵 ブロック Triple-DES
5 共通鍵 ブロック RC2 RFC 2268
6 共通鍵 ストリーム RC4 RFC 7465
7 公開鍵 - RSA 大きな数の素因数分解問題
8 公開鍵 - El Gamal 離散対数問題
9 公開鍵 - ECC 離散対数暗号方式に楕円曲線の点のグループを適用させた方式

暗号利用モード (Block cipher modes of opration)

暗号化のアルゴリズムとは別に、暗号化を行う手順についての規格(?)。

また、このモードはブロック暗号と呼ばれる暗号方式の際に利用する。

代表的なECBモードといわれる方法では、鍵で平文を暗号化する際に単純に一回暗号化処理を行う。この状態では、同じ平文を同じパスワードで暗号化した場合、暗号化結果が同一になってしまうため、パターンを解析することで平文が求められてしまう。

これを防ぐためのやり方がそのほかのモードである。

ECB(Electronic Codebook)モード

最も単純な暗号利用モードである。 平文を決まったブロック(長さ)に分けたのち、そのブロックをそれぞれ独立して暗号化する。

EBCモードの欠点は、上記にも記載した通り、同じ鍵を用いた場合ある平文ブロックを暗号化した結果の暗号ブロックが常に同じになることである。

CBC(Cipher Block Chaining)モード

この方式はIBMによって考案された方式で、各ブロックの平文を前のブロックのXORをとってから暗号化させる。

この方法をとることによって、同一のパスワード・平文であったとしても、文脈が異なれば暗号化結果が変わる状態となる。

また、最初のブロックについては、前のブロックが存在しないため、代わりになるInitialization Vector(IV)という初期値を与える。

これは、最初のブロックに対して前のブロックの代わりになるため、ブロック長と同じ長さを指定する必要がある。

この方式の欠点は以下の2点があげられる。

  • ブロックの暗号化に前のブロックの情報が必要であるため、暗号化は並列で行うことができない。
  • 暗号ブロックの長さを固定化しなければならないため、対象の平文をブロック長の整数倍の長さにパディング(空白埋めなど)しなければならない。

Niels FergusonおよびBruce Schneierによって推奨される二つの暗号化の一つである。

PCBC(Propagating Cipher Block Chaining)モード

あまり主流ではないCBCモードの変法である。

CBCモードでは、前のブロックの暗号結果を次のブロックに対してXORをかけた後に鍵で暗号化をかけていたが、PCBCモードでは、前のブロックの暗号化結果とそのブロックの暗号化前の平文をXORした結果で次のブロックの平文をXORし、鍵で暗号化する。

特徴としては、隣接する2つの暗号文ブロックを入れ替えたとしてもそれ以降のブロックの複合に影響しないこと。

CFB(Cipher Feedback)モード

CBCモードと似ているが、どちらを主として考えるかという違いのようである。

手順としては、IV(または前の暗号化結果)を暗号化し、その結果に次のブロックをXORして暗号化結果とする。

これは、CBCモードと同様に、並列処理ができない作りである。

また、これもCBCモードと同様だが、平文1ビットの変更で暗号文全体が変わってしまう。

CBCモードと比べて利点となるのは、パディング処理を行わなくともよいという点である。

OFB(Output Feedback)モード

CFBモードの亜種みたいなもので、次のブロックの元となる暗号化ブロックを、前のブロックでXORをかける前の暗号化ブロックを用いる。

利点としては、暗号化前でも前方誤り補正を適用できることのようだが、正確な意味を理解できていない。。。[TODO]

また、細かい部分の説明を省くが、CBCモードを入力がすべて0で実施したときの暗号化ブロックが、OFBモードのブロックごとの入力値となるため、ハードウェア的な高速CBC機構を用いてOFBモードを実施する事が可能である。

CTR(Counter)モード

Counterと呼ばれる値とNonceと呼ばれる値を組み合わせ、暗号化処理をかけた結果を平文のブロックにXORすることで暗号化する。

Counterは単調増加であり値が重複することがなければどんな値でもよいが、1ずつ増加する値を用いることが一般的である。

また、この方式では暗号化・複合化ともに並列処理が行えるため、複数プロセッサと相性が良い。

さらに、Niels FergusonおよびBruce Schneierによって推奨される2つの暗号化の一つである。

その他

  • CTS(CipherText Stealing)
  • 2DEM(2D Encryption Mode)
  • ABC(Accumulated Block Chaining)
  • IGE(Infinite Garble Extension)
  • F8@3GPP

などなど

参考文献

  1. Wikipedia - 暗号利用モード
  2. triplefalcon - ブロック暗号化モード

パディングモード

暗号化モードでパディング処理が必要であるが、このパディングについても手法がいくつかある。

NoPadding

単純で、パディングを行わないモード これで問題ないのか?

ZeroBytePadding

ブロック長に満たない場合はNULLバイト(0x00)で埋める。 ブロック長ピッタリな場合はパディングされない。

このため、末尾のNULLバイトが本来生成された値の末尾なのかパディングされた値なのかを判断できない。

暗号化するデータにNULLバイトが含まれていない場合に用いれる。

PKCS#5 Padding

ブロック長に満たないサイズの値を表すバイト値で足りない分を埋める。

不足分が変われば埋める値が変わる。

ブロック長がピッタリな場合は1ブロック分丸ごとパディングされる。

RFC1423で規格化されている。

PKCS#7 Padding

バイト シーケンスで構成され、各バイト シーケンスは追加される埋め込みバイトの合計数に等しいバイト数になる。

RFC5652で規格化されている。

.NETではPKCS方式の場合このバージョンが実装されている。

たとえば以下の通り。

FF FF FF FF FF FF FF FF FF 07 07 07 07 07 07 07

ISO10126Padding

W3Cで定義されているパディング方式

ランダムな値で埋める。

たとえば以下の通り。

FF FF FF FF FF FF FF FF FF 7 D 2A 75 EF F8 EF 07

SSL3Padding

SSL Protocol バージョン3.0のセクション5.2.3.2(CBCブロック暗号)で規定されたパディング方式

ANSIX923 Padding

ブロック長に満たないサイズの値を表すバイトを最後につけたNULLバイト値で埋める。

たとえば以下の通り。

FF FF FF FF FF FF FF FF FF 00 00 00 00 00 00 07

参考資料

  1. MSDN - PaddingMode 列挙型
  2. Pentan.info - [暗号化]ブロック暗号とは(AES/DES/Blowfish PKCS5Padding ECB/CBC IV)

参考資料

  1. ネットワークエンジニアとして - Common key cryptosystem / Public key cryptosystem
  2. @IT - 第1回 暗号化の基礎
  3. 情報社会におけるセキュリティ - 2-4 暗号化アルゴリズム

ハッシュ化アルゴリズム

暗号化とは似て異なる代物で、暗号化では可逆の暗号文を生成するが、ハッシュでは不可逆の暗号文(メッセージダイジェストとかフィンガープリントとか呼ぶらしい)を生成する。

また、可変のデータ長の平文を一定のデータ長の値を求めることができるため、チェックディジットや、パスワードの保管などに使われる。

使用方法から、ハッシュでは暗号化と異なった特性が求められる。

  • ハッシュは同じハッシュ関数を通す場合は常に同じ値が求まる。
  • 異なる元メッセージから同じハッシュ値が生成され にくい
  • また、生成されたハッシュ値と同一のハッシュ値が生成されるメッセージを求めることが困難であること。

ハッシュ化アルゴリズムの種類

ハッシュ化アルゴリズム一覧

# ハッシュアルゴリズム 信頼度 規格 備考
1 MD5 RFC 1321 _
2 SHA-1 FIPS 180-2 _
3 SHA-2 FIPS 180-4 _
4 SHA-3 ? _

参考資料

  1. シニアエンジニアの庵 - ハッシュ関数

ソルト

ハッシュ化アルゴリズムの特性上、同じ平文を与えた場合常にハッシュ化された値は同じになることが保証されている。

この特性をついて、よく設定される平文に対応するハッシュ値をデータベース化し、これと突き合わせることによって平文を求めるという手法(レインボーテーブル)に弱いことが知られている。

この対策のため、平文に「ある値」をつなげた結果をハッシュ化し、「ハッシュ値」とこの「ある値」を一緒に管理するという手法がとられている。

この「ある値」をソルトと呼んでいる。

パスワードの管理であれば、パスワードを入力された後、このパスワードと保管しておいたソルトをつなげハッシュ値を求める。このハッシュ値が保管しているハッシュ値と一致していれば、入力されたパスワードが正しいと判断できる。

また、レインボーテーブルへの対応としては以下の要件を満たすべきである。

  • 平文ごとに異なるソルトを使う
  • ある程度の長さ(20文字程度以上)を確保する

ストレッチング

ストレッチングは総当たりによる解読の対策として生まれた手法。

ハッシュの使用目的として、処理速度は高速であることが求められるため、この高速性をついて総当たりでの平文探索を行われてしまうことがある。

これの対策として、あえて遅いハッシュ関数を作成するのではなく、早いハッシュ関数を何千回と繰り返すことで処理自体を遅くし、総当たりに時間がかかるようにする手法がストレッチングである。

ストレッチングの回数が多いほど安全性が高まるが、計算量が増えることで負荷がかかってしまう。

この負荷を利用してDoS攻撃に悪用されるリスクが高まってしまう。

参考資料

  1. けんごのお屋敷 - 理解してるつもりの SSL/TLS でも、もっと理解したら面白かった話
  2. Qiita - 暗号化とハッシュ化に関する基本的な事柄まとめ