Lesson 15

データの暗号化

Lesson 15 Chapter 1
ハッシュ値とは

ハッシュ値とは、元データに対して生成された値のことを言います。元データをハッシュ化する処理が記述されたものをハッシュ関数と呼びます。 データを簡潔に表すことでデータの保存や検索などに利用されたり、パスワードなどの元データとして保管できないデータをハッシュ化することで暗号化の役割も果たします。

ハッシュ化に利用される要素と流れ

ハッシュ化には主に3つの要素が関わっています。

  • 元データ
  • ソルト
  • ハッシュアルゴリズム

ソルトとハッシュアルゴリズムについて、もう少し詳しく見ていきましょう。

ソルトについて

ソルトとはハッシュ化の際に元データと掛け合わせる要素です。ハッシュアルゴリズムはハッシュ化の仕組みを持っており、元データとソルトを元にハッシュ値を計算します。 ハッシュ値を復号化する(元データに戻す)にはソルトを元に、ハッシュ化とは逆のアルゴリズムで計算をすることで割り出すことが出来ます。

例として簡単なハッシュ化の流れを見てみます。3要素の情報は以下の通りです。

  • 元データ:「1234」
  • ハッシュ値:「5」
  • ハッシュアルゴリズム:「すべての桁にハッシュ値を加算する」

この要素でハッシュ化を行うと6789というハッシュ値が計算されます。復号化ではこの逆の手順を行うことになります。

ハッシュアルゴリズムについて

ハッシュアルゴリズムには様々なものがあり、それぞれ特徴があります。

アルゴリズム 説明
MD5 128ビットのハッシュ値を生成。脆弱性が発見されていて、セキュリティに問題がある。
SHA-1 160ビットのハッシュ値を生成。脆弱性が発見されていて、セキュリティに問題がある。
SHA-256 256ビットのハッシュ値を生成。現在でもセキュリティに問題はなく使用されている。

例えば、MD5やSHA-256などは古くから使われているアルゴリズムですが、最近ではそれらを攻撃する手法が発見されることが多いため、安全性が高いものが求められています。 そのため最近ではbcryptやscryptなどといった、より多くの計算量が必要となるアルゴリズムが利用される事があります。

bcryptの特徴

bcryptはランダムなソルトを使用してパスワードをハッシュ化するため、攻撃者がパスワードを事前に計算して作るハッシュテーブルを使用した攻撃への耐性があります。 また、計算に時間がかかるように設計されているため、総当たり攻撃に対しても強力です。

bcryptの実際のハッシュ値は以下のようなものです。

$2a$10$N9qIa7YQf7gEkZP0oKYBwOw7pvW8OvZAyCNwo9t1b4V7sWtJvO4Z.

bcryptのハッシュ値には大きく4つの情報が含まれています。

範囲 実際のハッシュ値 説明
1~2番目の$に囲まれた部分 2a ハッシュアルゴリズムのバージョン
2~3番目の$に囲まれた部分 10 コストパラメータ
3番目の$以降から22文字 N9qIa7YQf7gEkZP0oKYBwO ランダムなソルト
上記以外の残り部分(後ろから31文字) 7pvW8OvZAyCNwo9t1b4V7sWtJvO4Z. 最終的なハッシュ値

コストパラメータとは、ハッシュ関数を用いてハッシュ化する回数を決定するための数値です。 上記の例の場合、コストパラメータが「10」となっており、これは2の「10」乗(1024)回ハッシュ化をするということになります。 これにより、ブルートフォースアタックと呼ばれる総当り攻撃では、現実的ではない時間を要するようになり事実上解析不可能となります。

scryptの特徴

scryptもbcryptと同様にランダムなソルトを使用したパスワードハッシュ関数の1つで、主にパスワードのハッシュ化に使用されます。 大きな違いとしては、一般的なハッシュ関数とは異なり大量のメモリを必要とすることです。これにより、攻撃者は大容量のメモリを用意するための大きなコストが必要となります。

ここまで様々なハッシュアルゴリズムについて学んできました。基本的には、ハッシュ値を復号化することは困難ですがハッシュ値を求めることは可能であるため、ハッシュ値を保管する際には暗号化も行うことが望ましいです。

次に、ハッシュ化と似たような概念であるBase64という有名なエンコード方式について学んでいきましょう。

Lesson 15 Chapter 2
Base64とは

base64とは、データを64種類の文字で表現するエンコード方式のことを指します。また、エンコードとはデータを他の形式へ変換することです。 base64では、ASCII文字のみを使用します。ASCII文字は、0~127の番号を持つ文字のことで、このASCII文字の中から64種類を選び出し、それぞれに対応する番号を割り当てます。

以下がASCIIコード表になります。

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 NUL SOH STX ETX EOT ENQ ACK BEL BS TAB LF VT FF CR SO SI
1 DLE DC1 DC2 DC3 DC4 NAK SYN ETB CAN EM SUB ESC FS GS RS US
2 SP ! " # $ % & ' ( ) * + , - . /
3 0 1 2 3 4 5 6 7 8 9 : ; = > ?
4 @ A B C D E F G H I J K L M N O
5 P Q R S T U V W X Y Z [ \ ] ^ _
6 a b c d e f g h i j k l m n o
7 p q r s t u v w x y z { | } ~ DEL

また、データを64種類の文字で表現することができるため、テキスト形式でデータを保存することができます。 また、base64でエンコードされたデータは、ASCII文字のみを使用しているため、ほとんどのシステムで正常に表示されるというメリットがあります。

下の表は、8ビットバイナリデータとBase64文字の対応表の一部分です。

バイナリ Base64
000000 A
000001 B
000010 C
111110 +
111111 /

それでは実際に、普段コンピューター上で使用されるASCII文字をBase64でエンコードする流れを見ていきましょう。今回は「ABC」という文字をエンコードしてみます。

エンコードの流れ

まずは、「ABC」という3文字をエンコードする場合、それぞれの文字をASCIIコード対応表に従って8ビットバイナリデータに変換し、それを結合して1つの24ビットデータとします。

1. A B C のASCIIコードを確認(16進数)
> 0x41 0x42 0x43

2. 次に、16進数を2進数へ変換する
> 01000001 01000010 01000011

3. 以上3つのバイナリを1つに結合
> 010000010100001001000011

これで、エンコードする際の元データとなるバイナリデータが完成しました。 ここからBase64エンコード方式を利用してBase64文字へ変換していきます。

4. バイナリデータを6ビット単位で再度切り分ける
> 010000 010100 001001 000011

5. これらをBase64でエンコードすると「QUJD」の4文字となる
> Q U J D

以上が、Base64によるエンコードの流れです。

Base64の主な用途

Base64は、電子メールやHTTPなどのプロトコルで画像や音声などのバイナリデータをテキスト形式でやり取りするために使用されることが多いです。 また、パスワードやAPIキーなどのセキュリティ上重要な情報を暗号化するためにも使用されます。これは、暗号化アルゴリズムが使用できない場合や、暗号化したデータをテキスト形式でやり取りする必要がある場合に有効です。

ただし、Base64は暗号化ではなくエンコードの方法であり、安全性は高くありません。実際には暗号化とBase64を組み合わせることで、より安全性の高い通信を実現することができます。 このようにBase64によってバイナリデータを文字列に変換することで、テキスト形式でデータをやり取りすることができるようになります。