暗号化の概要

暗号化を使用すると、データが表示または変更されないように保護し、通常は安全でないチャネル上に安全な通信手段を確立するために役立ちます。たとえば、暗号化アルゴリズムを使用してデータを暗号化し、暗号化された状態で送信できます。送信先の相手は、後でこのデータを復号化できます。暗号化されたデータを第三者が傍受したとしても、復号化するのは困難です。

暗号化が使用される一般的な状況では、二者 (ここでは Alice と Bob) が安全でないチャネルを経由して通信します。Alice と Bob は、通信が第三者に傍受されたとしても、内容は理解されないという保証を必要としています。また、Alice と Bob は離れた場所にいるため、Alice には、Bob から受け取る情報が送信中に変更されていないことを確認する必要があります。さらに Alice には、Bob のふりをしただれかからではなく、本当に Bob からの情報を受け取ることができるという保証が必要です。

暗号化は、次の目標を達成するために使用されます。

  • 機密性。ユーザーの ID またはデータが読み取られないように保護するために役立ちます。

  • データの整合性。データが変更されないように保護するために役立ちます。

  • 信憑性。データが特定の人から送信されることを保証します。

これらの目標を達成するために、暗号プリミティブと呼ばれるアルゴリズムと手法の組み合わせを使用して暗号スキームを作成します。暗号プリミティブとその用途の一覧を次の表に示します。

暗号プリミティブ 使用方法

共有キー暗号方式 (対称暗号化方式)

データに対して変換処理を実行し、データが第三者に読み取られるのを防ぎます。このタイプの暗号方式では、単一の共有キーを使用してデータの暗号化と復号化が行われます。

公開キー暗号方式 (非対称暗号化方式)

データに対して変換処理を実行し、データが第三者に読み取られるのを防ぎます。このタイプの暗号方式では、公開キーと秘密キーのペアを使用してデータの暗号化と復号化が行われます。

署名の暗号化

送信元に固有のデジタル署名を作成することで、データが特定の人から送信されたことを確認することに役立ちます。この処理でもハッシュ関数が使用されます。

暗号ハッシュ

任意の長さのデータを固定長のバイト シーケンスに変換します。ハッシュは統計的に一意となります。つまり、異なる 2 バイトのシーケンスが同一の値にハッシュされることはありません。

共有キー暗号方式

共有キー暗号方式のアルゴリズムでは、単一の共有キーを使用したデータの暗号化と復号化が行われます。キーを取得した人はだれでもデータを復号化できるため、このキーは、承認されていないエージェントがアクセスできないように保護する必要があります。共有キー暗号方式は対称暗号化方式とも呼ばれます。これは、暗号化と復号化で同じキーが使用されるためです。共有キー暗号化アルゴリズムは (公開キー アルゴリズムと比較して) 非常に高速であり、大量のデータ ストリームに対して暗号変換を実行する場合に適しています。

一般に、データをブロック単位で暗号化するときには、ブロック暗号と呼ばれる共有キー アルゴリズムが使用されます。ブロック暗号 (RC2、DES、TripleDES、Rijndael など) では、n バイトの入力ブロックが、暗号化されたバイト数の出力ブロックに変換されます。バイト シーケンスを暗号化または復号化する場合は、ブロック単位で行う必要があります。n は小さいため (RC2、DES、および TripleDES では n = 8、Rijndael では n = 16 [既定]、n = 24、または n = 32)、n よりも大きいデータ値は 1 ブロックずつ暗号化する必要があります。

基本クラス ライブラリに用意されているブロック暗号クラスでは、暗号ブロック チェイン (CBC) と呼ばれるチェイン モードが使用されます。このモードでは、キーと初期化ベクタ (IV) を使用してデータの暗号変換が行われます。特定の共有キー k を使用する場合、初期化ベクタを使用しない単純なブロック暗号では、同じ平文の入力ブロックは同じ暗号文の出力ブロックに暗号化されます。平文ストリーム内にブロックを複製すると、暗号文ストリームにも重複するブロックが生成されることになります。承認されていないユーザーに平文のブロックの構造を知られると、その情報を使用して既知の暗号文ブロックを復号化できるため、キーが復元されてしまう可能性があります。この問題に対処するために、次のブロックを暗号化するプロセスには、前のブロックからの情報が組み込まれています。したがって、2 つの平文ブロックが同じでも、それぞれの出力は異なることになります。この方法では、次のブロックを暗号化するために前のブロックが使用されるため、データの先頭ブロックは IV を使用して暗号化されます。このシステムを使用した場合は、承認されていないユーザーが共通メッセージ ヘッダーを知っていたとしても、その情報からキーをリバース エンジニアリングすることはできません。

このタイプの暗号方式によって暗号化されたデータを解読する 1 つの方法は、考えられるすべてのキーを徹底的に探索することです。ただし、暗号化の実行時に使用したキーのサイズによっては、どれほど高速なコンピュータを使用してもかなりの時間がかかるため、この探索方法は現実的ではありません。キーのサイズを大きくするほど、復号化は困難になります。暗号化することにより、暗号データの復号化が理論的に不可能になるわけではありませんが、復号化にかかるコストを極端に大きくできます。3 か月をかけて徹底的な探索を行っても、取得されたデータが数日間しか意味を持たないとすると、その探索方法は実用的とはいえません。

共有キー暗号方式の弱点は、両者のキーと IV を一致させ、それぞれの値を転送しておく必要がある点です。さらに、承認されていないユーザーからキーを保護する必要もあります。このような問題のため、共有キー暗号方式は公開キー暗号方式と併用されることがよくあります。公開キー暗号方式は、キーと IV の値を秘密に通信するために使用されます。

安全でないチャネルを経由して Alice と Bob が通信しようとしている場合は、次のように共有キー暗号方式を使用することが考えられます。Alice と Bob の 2 人は、特定の 1 つのアルゴリズム (たとえば Rijndael) と、特定のキーおよび IV を使用することに合意します。Alice はメッセージを作成し、メッセージを送信するためのネットワーク ストリームを作成します。次に、キーと IV を使用してテキストを暗号化し、暗号化されたテキストをインターネット経由で送信します。キーと IV は Bob に送信しません。暗号化されたテキストを受信した Bob は、あらかじめ決めてあるキーと IV を使用して復号化を行います。通信が傍受されたとしても、傍受した人にはキーと IV がわからないため、元のメッセージが復元されることはありません。このシナリオでは、キーを秘密にしておく必要はありますが、IV を秘密にする必要はありません。実際のシナリオでは、Alice または Bob のどちらかが共有キーを生成し、公開キー (非対称) 暗号方式を使用して相手に共有 (対称) キーを転送することになります。詳細については、このトピックで後述する「公開キー暗号方式」を参照してください。

.NET Framework には、共有キー暗号化アルゴリズムを実装する次のクラスが用意されています。

公開キー暗号方式

公開キー暗号方式では、承認されていないユーザーから保護する必要のある秘密キーと、だれに公開してもかまわない公開キーが使用されます。公開キーと秘密キーは正確にリンクされ、公開キーで暗号化されたデータは、対応する秘密キーでしか復号化できません。また、秘密キーで署名されたデータは、対応する公開キーでしか検査できません。公開キーはだれに公開してもかまいません。公開キーは、秘密キーの所有者に送信するデータを暗号化するために使用されます。公開キーと秘密キーは、いずれも通信セッションに固有のキーです。公開キー暗号化アルゴリズムは非対称アルゴリズムとしても知られます。これは、データの暗号化に 1 つのキーが使用され、データの復号化に別のキーが使用されるためです。

公開キー暗号化アルゴリズムでは固定バッファ サイズが使用されますが、共有キー暗号化アルゴリズムでは可変長バッファが使用されます。公開キー アルゴリズムでは少量のデータしか暗号化できないため、共有キー アルゴリズムのようにデータをチェインしてストリームを作成することはできません。したがって、非対称操作では対称操作と同じストリーミング モデルは使用されません。

二者 (Alice と Bob) は次のように公開キー暗号方式を使用すると考えられます。まず、Alice は公開キーと秘密キーのペアを生成します。暗号メッセージを Alice に送信するとき、Bob は Alice に公開キーを送信するように依頼します。Alice は安全でないネットワークをとおして Bob に公開キーを送信し、Bob はこのキーを使用してメッセージを暗号化します(公衆ネットワークなどの安全でないチャネル経由で Alice のキーを受信した場合、Bob は、受信した公開キーが正しいかどうかを Alice に確認する必要があります)。Bob は暗号メッセージを Alice に送信し、Alice は自分の秘密キーを使用してメッセージを復号化します。

ただし、Alice の公開キーの転送中に、承認されていないエージェントによってキーが傍受される可能性があります。さらに、同じエージェントが Bob からの暗号メッセージを傍受する可能性もあります。しかし、公開キーを使用してもメッセージを復号化することはできません。メッセージを復号化できるのは Alice の秘密キーだけですが、これは送信されていません。Alice は Bob への返信メッセージを暗号化するときに自分の秘密キーを使用しません。公開キーを持つ人は、だれでもそのメッセージを復号化できるためです。Alice から Bob にメッセージを返信するときには、Alice が Bob の公開キーをたずね、その公開キーを使用してメッセージを暗号化します。その後、Bob は自分の秘密キーを使用してメッセージを復号化します。

実際のシナリオでは、Alice と Bob は公開キー (非対称) 暗号方式を使用して共有 (対称) キーを転送し、その他のセッションでは共有キー暗号方式を使用することになります。

公開キー暗号方式では、キースペース、つまりキーの値として使用できる範囲が大幅に広がり、あらゆるキーを試すような徹底的な攻撃の影響を受けにくくなります。公開キーは保護する必要がないため、簡単に配布できます。公開キー アルゴリズムを使用すると、データの送信元の ID を検査するデジタル署名を作成できます。ただし、公開キー アルゴリズムは (共有キー アルゴリズムと比較して) きわめて低速であり、大量のデータを暗号化するようにはデザインされていません。公開キー アルゴリズムが便利なのは、少量のデータを転送する場合に限られます。一般に、公開キー暗号方式は、共有キー アルゴリズムで使われるキーと IV を暗号化するために使用されます。キーと IV を転送した後の残りのセッションでは、共有キー暗号方式が使用されます。

.NET Framework には、公開キー暗号化アルゴリズムを実装する次のクラスが用意されています。

デジタル署名

公開キー アルゴリズムは、デジタル署名を形成するためにも使用できます。デジタル署名は、(送信元の公開キーを信頼している場合に) 送信元の ID を認証したり、データの整合性を保護することを支援したりします。Alice によって生成された公開キーを使用すると、Alice のデータの受信者は、Alice のデータに添付されたデジタル署名と Alice の公開キーを比較することによって、データの送信元が Alice かどうかを検査できます。

Alice は、公開キー暗号方式を使用してメッセージにデジタル署名を添付するために、まずメッセージに対してハッシュ アルゴリズムを適用してメッセージ ダイジェストを作成します。このメッセージ ダイジェストは、一意でコンパクトなデータ表現です。次に Alice は、自分の秘密キーを使用してメッセージ ダイジェストを暗号化し、個人用の署名を作成します。Bob は、メッセージと署名を受信したときに Alice の公開キーを使用して署名を復号化し、メッセージ ダイジェストを復元します。そして、Alice が使用したのと同じハッシュ アルゴリズムを使用してメッセージをハッシュします。Bob が計算したメッセージ ダイジェストが Alice から受け取ったメッセージ ダイジェストと正確に一致する場合、そのメッセージは秘密キーの所有者から送信されたことになり、データも変更されていないことが保証されます。Alice が秘密キーの所有者であることが確かならば、Bob にはメッセージが Alice から送信されたことがわかります。

送信者の公開キーは公開された情報であり、通常はデジタル署名の書式に含まれるため、だれでも署名を検査できることに注意が必要です。この方法では、メッセージの秘密性は保持されません。メッセージを秘密にしておくためには、メッセージ自体も暗号化する必要があります。

.NET Framework には、デジタル署名アルゴリズムを実装する次のクラスが用意されています。

ハッシュ値

ハッシュ アルゴリズムは、任意長のバイナリ値を、ハッシュ値と呼ばれる固定長の小さなバイナリ値に変換します。ハッシュ値はデータの数値表現であり、一意で非常にコンパクトです。平文の段落をハッシュし、段落の 1 文字を変更しただけでも、その後のハッシュでは別の値が生成されることになります。同一の値にハッシュされる 2 つの異なる入力を見つけるのは、計算上不可能です。

データに署名するためには、一般に MAC (Message Authentication Code) ハッシュ関数が使用されますが、データの整合性を保つ目的では、MDC (Message Detection Code) ハッシュ関数が使用されます。

二者 (ここでは Alice と Bob) の場合は、次のようにハッシュ関数を使用してデータの整合性を確保できます。Alice が Bob にメッセージを書き、そのメッセージのハッシュを作成したとします。Bob は、後からメッセージをハッシュして、作成されたハッシュと元のハッシュを比較します。ハッシュ値が一致した場合はメッセージは変更されていませんが、値が一致しない場合は、Alice が書いた後でメッセージが変更されたことになります。このシステムを機能させるために、Alice は元のハッシュ値を Bob 以外の人から隠す必要があります。

.NET Framework には、デジタル署名アルゴリズムを実装する次のクラスが用意されています。

乱数生成

乱数生成は、多くの暗号化操作に欠かせない部分です。たとえば、暗号キーはできるだけランダムにして、再現できないようにする必要があります。暗号乱数ジェネレータは、予測される確率が *p *< .05 よりも低い、計算上は測不可能な出力を生成する必要があります。つまり、当て推量をされた場合でも予測できないような手段を使用する必要があります。.NET Framework に含まれるクラスは、乱数ジェネレータを使用して暗号キーを生成します。

乱数ジェネレータ アルゴリズムは、RNGCryptoServiceProvider クラスに実装されています。

参照

概念

.NET Framework の暗号モデル

その他の技術情報

暗号タスク
暗号サービス