小池啓仁 ヒロヒト応援ブログ By はてな

小池啓仁(コイケヒロヒト)の動画など。

小池啓仁 ヒロヒト応援ブログ By はてな

WEBプログラマー必見!WEB暗号化基礎知識最速マスター

以下は、WEBプログラマー用のWEB暗号化の基礎知識の一覧です。
WEBプログラマーの人はこれを読めばWEB暗号化の基礎をマスターしてWEBプログラムを書くことができるようになっているかもです。
また、WEB暗号化の簡易リファレンスとしても少し利用できるかもしれません。
しかし、WEBアプリケーションを開発するには、暗号そのものを知らなくても、実は大丈夫なのです。
そう、OSI参照モデルのレイヤー(層)がWEBアプリケーションは7層で、暗号は5層になっているからです。
でも、httpsでの暗号や認証の方法が謎なので、やはり気になりますね。


今回、WEBで使われているhttpsのsの部分について調べてみました。
それには、まず『暗号とは』から始まって、『暗号方式』、『認証方式』そして、httpsのsの部分について解説していきますね。
また最後に、暗号技術の分類をご紹介します。

  • 暗号とは
  • 暗号方式
  • 認証方式
  • httpsのsの部分
  • 暗号技術の分類

このまとめがWEBアプリケーション開発の参考になれば幸いです。


尚、本コンテンツを作成するにあたって、以下のリンク先を大変参考にさせて頂きました。
下記のリンク先は、凄く勉強になりました。謹んで御礼申し上げます。


◆参考リンク



◆暗号とは

暗号とは、大辞泉では、『通信の内容が相手以外にわからないように、当事者の間だけで決めた記号』となっています。
通信の内容の元の文章を「平文」といい、これを相手以外にわからないように「暗号文」に変換することを暗号化といいます。
一方、「暗号文」を元の文章に戻すことを復号といい、暗号化や復号を行う手順を「アルゴリズム」といいます。
また、当事者の間だけで決めた暗号化に用いるパラメータのことを「鍵」といいます。


整理すると、暗号には、以下の4つの要素があります。

  1. 平文
  2. 暗号文
  3. アルゴリズム
■シーザー暗号での例

この要素について、シーザー暗号に当てはめてみると…まずは、シーザー暗号とは

古来から伝わる暗号化の方式としてシーザー暗号というのものがあります。
仕組みはとても簡単で、下の表のように文字列をアルファベット順に
数個ずらすだけです。この例では A〜Z を F〜Z・A〜E と、5つずらしています。


ABCDEFGHIJKLMNOPQRSTUVWXYZ
FGHIJKLMNOPQRSTUVWXYZABCDE

例えば「I LOVE YOU」というメッセージをこのシーザー暗号で
暗号化すると「N QTAJ DTZ」という暗号文になります。
暗号文を受信した側は、F〜Z・A〜E を 5つずらして A〜Z
に戻せば「I LOVE YOU」という平文が手に入ります。

http://x68000.q-e-d.net/~68user/net/crypt-1.html
  • 平文は、「I LOVE YOU」です。
  • 暗号文は、「N QTAJ DTZ」です。
  • アルゴリズムは、「アルファベット順に置き換える」です。
  • 鍵は、「5文字」です。

尚、「5文字」の鍵は、暗号化と復号で一つ(共通)ですが、暗号化は5文字後ろにずらし、復号は5文字前にずらします。
これは、ドアの鍵が一つで、右に回すとロックされ、左に回すとアンロックされるのと同じ感じです。


ついでにPerlでシーザー暗号してみました。

■実装仕様

仕様としては、アルファベット26文字のみ暗号化します。
暗号化(CaesarCipherEnc)としては、引数に平文とローテート数を指定します。
復号(CaesarCipherDec)としては、引数に暗号文とローテート数を指定します。

サンプルソース(ango.pl)
use strict;
use warnings;

    # 暗号化
    my $ans = CaesarCipherEnc('I LOVE YOU', 5);
    print $ans, "\n";

    # 復号
    $ans = CaesarCipherDec($ans, 5);
    print $ans, "\n";

sub CaesarCipherEnc {
# 第1引数は平文
# 第2引数はローテート数で0〜26
my ($intext, $rotate) = @_;
my  $wkABC1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ';
    return '引数エラー!' if (($rotate < 0) or ($rotate > length($wkABC1)/2));

my  $wkABC2 = substr($wkABC1, $rotate, length($wkABC1)/2);
    $_ = $intext;
    eval "tr/$wkABC1/$wkABC2/";
    return $_;
}

sub CaesarCipherDec {
# 第1引数は暗号文
# 第2引数はローテート数で0〜26
my ($intext, $rotate) = @_;
my  $wkABC1 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ';
    return '引数エラー!' if (($rotate < 0) or ($rotate > length($wkABC1)/2));

my  $wkABC2 = substr($wkABC1, length($wkABC1)/2 - $rotate, length($wkABC1)/2);
    $_ = $intext;
    eval "tr/$wkABC1/$wkABC2/";
    return $_;
}
サンプルソースの実行結果
C:\Documents and Settings\hoge>perl ango.pl
N QTAJ DTZ
I LOVE YOU
サンプルソースのポイント

アルファベットの変換にtr///を使用してます。
tr///は、s///と違って、文字列単位の置換ではなく、1文字単位の変換です。
また、tr///は、普通、変数を指定することはできませんが、evalを使うことにより可能にしています。
これは、"tr/$wkABC1/$wkABC2/"の文字列展開をした後にevalで実行ができるためです。
また、『eval "tr/$wkABC1/$wkABC2/";』で変換されるべき変数は『$_』なので、先に$intextを$_に代入しています。



◆暗号方式

つぎに暗号方式には、共通鍵暗号方式と公開鍵暗号方式の2つと、この両方を使うハイブリッド方式などがあります。

共通鍵暗号方式

たとえば、Aさんは、Bさんへメールをしたいのですが、盗聴が気になるので暗号化して送るとします。
そこで、Aさんは、鍵を使ってメールを暗号化して、Bさんへ送りました。
Bさんは、受け取った暗号化されたメールをAさんと同じ鍵を使って復号しました。
このように、AさんとBさんが同じ鍵を使って暗号文のやりとりを共通鍵暗号方式と言います。
しかし、決定的な欠点がありますね。そう、AさんとBさんは、予め同じ鍵をもっていないとなりません。
つまり、暗号化して送っても同じ鍵をもっていないと復号が出来ないのです。
そこで、この欠点を補う公開鍵暗号方式が出てきました。


共通鍵暗号方式をまとめると

  1. 送信者は、平文を共通鍵で暗号化して送信します。
  2. 受信者は、暗号化された平文を共通鍵で復号します。
公開鍵暗号方式

共通鍵暗号方式は、暗号化と復号を同じ鍵(共通鍵)を使いました。
しかし、公開鍵暗号方式は、暗号化と復号で別の鍵を使用するのです。
そして、暗号化する鍵は、公開してしまうのです!
まず、AさんはBさんの公開鍵でメールを暗号化して送ります。
Bさんは、自分が持っている秘密鍵でこのメールを復号するのです。
これで、共通鍵暗号方式の欠点を補えました。
しかし、公開鍵暗号方式は、暗号化・復号に非常に時間がかかる(共通鍵方式の数百〜千倍遅)という欠点があるのです。
そこで、この欠点を補う「共通鍵を公開鍵方式を用いて暗号化する」というハイブリッド方式が出てきました。


公開鍵暗号方式をまとめると

  1. 送信者は、受信者の公開鍵を取得します。
  2. 送信者は、平文を公開鍵で暗号化して送信します。
  3. 受信者は、暗号化された平文を秘密鍵で復号します。
■ハイブリッド方式

ハイブリッド方式は、共通鍵暗号方式と公開鍵暗号方式のハイブリッドです。
まず、Aさんは、暗号化が速い共通鍵でメールを暗号化します。
つぎに、Aさんは、Bさんの公開鍵で共通鍵を暗号化します。
そして、暗号化された共通鍵とメールを一緒にBさんへ送ります。
一方、Bさんは、暗号化された共通鍵を秘密鍵で復号します。
つぎに、Bさんは、復号された共通鍵でメールを復号します(めでたしめでたし)。
実は、これ、httpsもこの方式なのです!


・ハイブリッド方式をまとめると

  1. 送信者は、平文を共通鍵で暗号します。
  2. 送信者は、受信者の公開鍵を取得します。
  3. 送信者は、共通鍵を公開鍵で暗号化します。
  4. 送信者は、暗号化した共通鍵と平文を送信します。
  5. 受信者は、暗号化された共通鍵を秘密鍵で復号します。
  6. 受信者は、暗号化された平文を共通鍵で復号します。



◆認証方式

httpsの認証方式は、公開鍵証明書に基づく認証です。
通常、サーバだけが証明書を提示し、クライアントがその正当性を確認します。
そして、なりすましを防ぐために、証明書には認証局 (CA; Certification Authority) による電子署名が必要となります。

電子署名について

電子署名は、同じ内容の平文と秘密鍵での暗号文を送って、送られた方は、公開鍵で暗号文を復号して、平文と同じになれば、署名が正しとします。
しかし、このままでは、公開鍵暗号方式なので暗号化・復号に非常に時間かかります。
そこで、ハッシュ(128〜512 bit 程度なので暗号化・復号に時間がかからない)という機能を使い、平文をハッシュ値にして、それを暗号化し平文と一緒に送ります。
送られた方は、まず、暗号化されたハッシュ値を公開鍵で復号し、つぎに平文のハッシュ値を求め、両方が一致したら署名が正しいことがわかります。


・留意点
電子署名について公開鍵暗号方式が使えるのは、暗号アルゴリズムRSAの時だけです。
実際の電子署名でのアルゴリズムは、署名専用のDSAが使われることが多いとのことです。
また、秘密鍵で平文を暗号化しても、誰でも公開鍵で復号できるので、広い意味で暗号ではないですね。


電子署名をまとめると

  1. 送信者は、平文をハッシュ値に変換します。
  2. 送信者は、ハッシュ値秘密鍵で暗号化します。
  3. 送信者は、平文と暗号化されたハッシュ値を送信します。
  4. 受信者は、暗号化されたハッシュ値を公開鍵で復号します。
  5. 受信者は、平文をハッシュ値に変換します。
  6. 受信者は、両方のハッシュ値が一致したら電子署名が正しいと判断します。


ちなみに、なぜ、同じ内容の平文と暗号文を送って、受け取り側で暗号文を復号した結果、平文と同じになると電子署名が正しいとするかは、送り側が本人以外誰も知らない秘密鍵で暗号化するからです。
つまり、本人以外誰も知らない秘密鍵で暗号化ができ、それを復号して平文と内容が一致すれば、確かに本人の署名と言えるわけです。



httpsのsの部分

httpsのsの部分は、Secure Sockets Layer(セキュアソケットレイヤー、SSL)のsで、セキュリティーを要求される通信のためのプロトコルです。
始めに、ブラウザから『https://』のWEBページにアクセスすると、WWWサーバとブラウザの間で双方で使用できる暗号を確認し決定します。
つぎに、ブラウザは、WWWサーバからの証明書を受け取り、証明書内の『認証局』で署名された電子署名を予めブラウザが持っている公開鍵により解読して正当性を確認します。(要はWWWサーバが本物かの認証確認)
正当性を確認したら、ブラウザは次ぎに、通信で使用する共通鍵を生成し、先のWWWサーバの証明書に含まれていたサーバの公開鍵(予めブラウザが持っている公開鍵とは別物)で暗号化して、WWWサーバに送信します。
WWWサーバは、それを秘密鍵で復号して共通鍵を求めます。
以後は、この共通鍵で暗号化された電文をHTTPベースで通信します。
つまり、httpsのポイントは、サーバーの認証と通信の暗号化です。


httpsをまとめると

  1. ブラウザから『https://』のWEBページにアクセスします。
  2. WWWサーバとブラウザの間で双方で使用できる暗号を確認し決定します。
  3. ブラウザは、WWWサーバからの証明書を受け取ります。
  4. ブラウザは、証明書の電子署名を予めブラウザが持っている公開鍵により解読して正当性を確認します。
  5. ブラウザは、通信で使用する共通鍵を生成します。
  6. ブラウザは、証明書に含まれていた公開鍵を取得します。
  7. ブラウザは、生成した共通鍵を公開鍵で暗号化しWWWサーバに送信します。
  8. WWWサーバは、暗号化された共通鍵を秘密鍵で復号します。
  9. 以後は、この共通鍵で暗号化された電文をHTTPベースで通信します。


・予めブラウザが持っている公開鍵とは
IEWINDOWS)では、実は、結構沢山の認証局の公開鍵をレジストリに持っています。メニューバーのツールから確認ができます。ツール内のインターネットオプションから辿ってみてください。

  • インターネットオプション->コンテンツ->証明書->信頼されたルート証明機関->選択->表示->詳細

そこに「公開鍵」として、予め持っているわけです。



◆暗号技術の分類

最後に暗号技術の分類を紹介をしときます。


鍵の方式には、共通鍵暗号方式と公開鍵暗号方式があります。
また、両方を使う「共通鍵を公開鍵方式を用いて暗号化する」ハイブリッド方式もあります。


共通鍵暗号方式と公開鍵暗号方式には、各々アルゴリズム複数もっています。
共通鍵暗号方式アルゴリズムの種類には、ブロック暗号化方式とストリーム暗号方式の2つがあります。
また、ブロック暗号化方式には、ブロック暗号化モードを複数もっています。
ブロック暗号化モードは、ブロック化されることによるブロック単位での「暗号文一致攻撃」を防ぎやすくするモードです。


整理すると、以下のようになっています。