次の方法で共有


.NET での暗号化、デジタル署名、ハッシュ アルゴリズムの概要

この記事では、ClickOnce マニフェストなど、.NET でサポートされる暗号化方法とプラクティスの概要について説明します。

暗号化の概要

インターネットなどのパブリック ネットワークでは、エンティティ間のセキュリティで保護された通信手段は提供されません。 このようなネットワーク上の通信は、承認されていない第三者によって読み取られたり、変更されたりする可能性があります。 暗号化は、データが表示されないように保護し、データが変更されたかどうかを検出する方法を提供し、それ以外の場合はセキュリティで保護されていないチャネル経由で安全な通信手段を提供するのに役立ちます。 たとえば、暗号化アルゴリズムを使用してデータを暗号化し、暗号化された状態で送信し、後で目的のパーティによって復号化することができます。 第三者が暗号化されたデータを傍受した場合、解読が困難になります。

.NET では、 System.Security.Cryptography 名前空間のクラスが暗号化の多くの詳細を管理します。 オペレーティング システム実装のラッパーもあれば、純粋に管理された実装であるものもあります。 これらのクラスを使用するために、暗号化の専門家である必要はありません。 暗号化アルゴリズム クラスの 1 つの新しいインスタンスを作成すると、使いやすくするためにキーが自動生成され、既定のプロパティは可能な限り安全で安全です。

暗号プリミティブ

暗号化が使用される一般的な状況では、2 つのパーティ (Alice と Bob) がセキュリティで保護されていないチャネルを介して通信します。 Alice と Bob は、聞いている可能性のあるすべてのユーザーがコミュニケーションを理解できないようにしたいと考えています。 さらに、Alice と Bob はリモートの場所にあるため、Alice は、Bob から受信した情報が転送中に誰も変更されていないことを確認する必要があります。 さらに、Bob を偽装しているユーザーではなく、情報が実際に Bob から送信されていることを確認する必要があります。

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

  • 機密性: ユーザーの ID またはデータが読み取られるのを防ぐことができます。

  • データの整合性: データの変更を防ぐことができます。

  • 認証: データが特定のパーティから送信されていることを確認します。

  • 否認不可: 特定のパーティがメッセージを送信したことを拒否できないようにするため。

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

暗号化プリミティブ 用途
秘密鍵暗号化 (対称暗号化) データに対して変換を実行して、サード パーティがデータを読み取れないようにします。 この種類の暗号化では、1 つの共有シークレット キーを使用して、データの暗号化と暗号化解除を行います。
公開キー暗号化 (非対称暗号化) データに対して変換を実行して、サード パーティがデータを読み取れないようにします。 この種類の暗号化では、公開キーと秘密キーのペアを使用して、データの暗号化と暗号化解除を行います。
暗号化署名 特定のパーティに固有のデジタル署名を作成することで、データが特定のパーティから送信されたことを確認するのに役立ちます。 このプロセスでは、ハッシュ関数も使用されます。
暗号化ハッシュ 任意の長さのデータを固定長バイト シーケンスにマップします。 ハッシュは統計的に一意です。異なる 2 バイト シーケンスでは、同じ値にハッシュされません。

Secret-Key 暗号化

秘密鍵暗号化アルゴリズムでは、1 つの秘密鍵を使用してデータの暗号化と暗号化解除を行います。 承認されていないエージェントによるアクセスからキーをセキュリティで保護する必要があります。これは、キーを持つすべてのパーティがキーを使用してデータの暗号化を解除したり、自分のデータを暗号化したりして、自分から送信されたデータを要求できるためです。

秘密鍵の暗号化は、暗号化と暗号化解除に同じキーが使用されるため、対称暗号化とも呼ばれます。 秘密鍵暗号化アルゴリズムは非常に高速であり (公開キー アルゴリズムと比較して)、大規模なデータ ストリームで暗号化変換を実行するのに適しています。 RSA などの非対称暗号化アルゴリズムは、暗号化できるデータの量に数学的に制限されます。 対称暗号化アルゴリズムには、通常、これらの問題はありません。

ブロック暗号と呼ばれる秘密キー アルゴリズムの種類は、一度に 1 ブロックのデータを暗号化するために使用されます。 Data Encryption Standard (DES)、TripleDES、Advanced Encryption Standard (AES) などのブロック暗号は、 n バイトの入力ブロックを暗号化されたバイトの出力ブロックに暗号によって変換します。 バイトシーケンスを暗号化または復号化する場合は、ブロックごとにブロックする必要があります。 n は小さいため (DES および TripleDES の場合は 8 バイト、AES の場合は 16 バイト (既定値)、24 バイト、または 32 バイト)、n より大きいデータ値は一度に 1 ブロックずつ暗号化する必要があります。 処理するには、 n より小さいデータ値を n に展開する必要があります。

ブロック暗号の 1 つの単純な形式は、電子コードブック (ECB) モードと呼ばれます。 ECB モードは、最初のプレーンテキスト ブロックを初期化するために初期化ベクターを使用しないため、セキュリティで保護されているとは見なされません。 特定の秘密鍵 k について、初期化ベクトルを使用しない単純なブロック暗号は、プレーンテキストの同じ入力ブロックを同じ暗号文の出力ブロックに暗号化します。 したがって、入力プレーンテキスト ストリームに重複するブロックがある場合は、出力暗号テキスト ストリームに重複するブロックがあります。 これらの重複する出力ブロックは、脆弱な暗号化に対して未承認のユーザーに対して、使用されている可能性のあるアルゴリズムと攻撃の可能性のあるモードを警告します。 したがって、ECB 暗号モードは分析に対して非常に脆弱であり、最終的にはキー検出に対して非常に脆弱です。

基底クラス ライブラリで提供されるブロック暗号クラスは、暗号ブロック チェーン (CBC) と呼ばれる既定のチェーン モードを使用しますが、必要に応じてこの既定値を変更できます。

CBC 暗号は、初期化ベクトル (IV) を使用してプレーンテキストの最初のブロックを暗号化することで、ECB 暗号に関連する問題を克服します。 プレーンテキストの後続の各ブロックは、暗号化される前に、前の暗号テキスト ブロックでビットごとの排他的 OR (XOR) 操作を受けます。 したがって、各暗号テキスト ブロックは、前のすべてのブロックに依存します。 このシステムを使用する場合、承認されていないユーザーに知られている可能性がある一般的なメッセージ ヘッダーを使用してキーをリバース エンジニアリングすることはできません。

CBC 暗号で暗号化されたデータを侵害する 1 つの方法は、考えられるすべてのキーを徹底的に検索することです。 暗号化を実行するために使用されるキーのサイズに応じて、この種の検索は最速のコンピューターでも非常に時間がかかり、そのため不可能です。 キー サイズを大きくすると、解読が困難になります。 暗号化では、敵対者が暗号化されたデータを取得することは理論的には不可能ではありませんが、これを行うコストは高くなります。 数日間だけ意味のあるデータを取得するために網羅的な検索を実行するのに 3 か月かかる場合、網羅的な検索方法は実用的ではありません。

秘密鍵の暗号化の欠点は、2つの当事者がキーとIVに同意し、その値を伝えていると仮定することです。 IV はシークレットとは見なされず、メッセージと共にプレーンテキストで送信できます。 ただし、キーは承認されていないユーザーから秘密にしておく必要があります。 これらの問題のため、秘密キー暗号化は、多くの場合、キーと IV の値をプライベートに通信するために公開キー暗号化と共に使用されます。

Alice と Bob がセキュリティで保護されていないチャネルを介して通信する 2 つの当事者であると仮定すると、Alice と Bob は、特定のキーと IV で 1 つの特定のアルゴリズム (AES など) を使用することに同意します。 Alice はメッセージを作成し、メッセージを送信するネットワーク ストリーム (名前付きパイプまたはネットワーク メールなど) を作成します。 次に、キーと IV を使用してテキストを暗号化し、暗号化されたメッセージと IV をイントラネット経由で Bob に送信します。 Bob は、暗号化されたテキストを受け取り、IV を使用して暗号化を解除し、以前に同意したキーを使用します。 転送がインターセプトされた場合、インターセプターはキーを認識していないため、元のメッセージを回復できません。 このシナリオでは、キーのみがシークレットのままである必要があります。 実際のシナリオでは、Alice または Bob が秘密キーを生成し、公開キー (非対称) 暗号化を使用してシークレット (対称) キーを相手に転送します。 公開キー暗号化の詳細については、次のセクションを参照してください。

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

  • Aes

  • HMACSHA256HMACSHA384HMACSHA512。 (これらは、暗号化ハッシュ関数と秘密鍵を組み合わせて計算されるメッセージ認証コードを表すので、技術的には秘密鍵アルゴリズムです。この記事の後半の ハッシュ値を参照してください)。

Public-Key 暗号化

公開キー暗号化では、承認されていないユーザーから秘密を保持する必要がある秘密キーと、すべてのユーザーに公開できる公開キーが使用されます。 公開キーと秘密キーは数学的にリンクされています。公開キーで暗号化されたデータは秘密キーでのみ復号化でき、秘密キーで署名されたデータは公開キーでのみ検証できます。 公開キーは誰でも使用できます。これは、秘密キーのキーパーに送信されるデータを暗号化するために使用されます。 公開キー暗号化アルゴリズムは、データを暗号化するために 1 つのキーが必要であり、データの暗号化を解除するために別のキーが必要であるため、非対称アルゴリズムとも呼ばれます。 基本的な暗号化規則ではキーの再利用が禁止されており、両方のキーは通信セッションごとに一意である必要があります。 ただし、実際には、非対称キーは一般に有効期間が長いです。

2 つのパーティ (Alice と Bob) は、次のように公開キー暗号化を使用できます。まず、Alice は公開キーと秘密キーのペアを生成します。 Bob が Alice に暗号化されたメッセージを送信する場合は、公開キーを要求します。 Alice はセキュリティで保護されていないネットワーク経由で Bob に公開キーを送信し、Bob はこのキーを使用してメッセージを暗号化します。 Bob は、暗号化されたメッセージを Alice に送信し、秘密キーを使用して暗号化を解除します。 Bob がパブリック ネットワークなどのセキュリティで保護されていないチャネルを介して Alice のキーを受け取った場合、Bob は中間者攻撃に対して開放されます。 そのため、Bob は Alice に公開キーの正しいコピーがあることを確認する必要があります。

Alice の公開キーの送信中に、承認されていないエージェントがキーを傍受する可能性があります。 さらに、同じエージェントが Bob から暗号化されたメッセージをインターセプトする可能性があります。 ただし、エージェントは公開キーを使用してメッセージを復号化できません。 メッセージは、送信されていない Alice の秘密キーでのみ復号化できます。 公開キーを持つすべてのユーザーがメッセージを復号化できるため、Alice は自分の秘密キーを使用して Bob への応答メッセージを暗号化しません。 Alice が Bob にメッセージを送り返す場合、Bob に公開キーを要求し、その公開キーを使用してメッセージを暗号化します。 Bob は、関連付けられている秘密キーを使用してメッセージの暗号化を解除します。

このシナリオでは、Alice と Bob は公開キー (非対称) 暗号化を使用してシークレット (対称) キーを転送し、セッションの残りの部分で秘密鍵暗号化を使用します。

次の一覧では、公開キー暗号化アルゴリズムと秘密鍵暗号アルゴリズムの比較を示します。

  • 公開キー暗号化アルゴリズムでは固定バッファー サイズが使用されますが、秘密鍵暗号化アルゴリズムでは可変長バッファーが使用されます。

  • 少量のデータしか暗号化できないため、公開キー アルゴリズムを使用して、秘密キー アルゴリズムが可能な方法でデータをストリームに連結することはできません。 そのため、非対称操作では、対称操作と同じストリーミング モデルは使用されません。

  • 公開キー暗号化には、秘密鍵暗号化よりもはるかに大きなキースペース (キーに使用できる値の範囲) があります。 そのため、公開キーの暗号化は、すべての可能なキーを試す徹底的な攻撃の影響を受けにくいです。

  • 公開キーは、送信者の ID を確認するための何らかの方法が存在する場合、セキュリティで保護する必要がないため、簡単に配布できます。

  • 一部の公開キー アルゴリズム (RSA や DSA など、Diffie-Hellmanではない) を使用してデジタル署名を作成し、データの送信者の ID を確認できます。

  • 公開キー アルゴリズムは、秘密鍵アルゴリズムと比較して非常に低速であり、大量のデータを暗号化するようには設計されていません。 公開キー アルゴリズムは、非常に少量のデータを転送する場合にのみ役立ちます。 通常、公開キー暗号化は、秘密鍵アルゴリズムによって使用されるキーと IV を暗号化するために使用されます。 キーと IV が転送されると、セッションの残りの部分で秘密鍵暗号化が使用されます。

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

RSA では暗号化と署名の両方が可能ですが、DSA は署名にのみ使用できます。 DSA は RSA ほど安全ではないため、RSA をお勧めします。 Diffie-Hellman は、キーの生成にのみ使用できます。 一般に、公開キー アルゴリズムの使用は秘密キー アルゴリズムよりも制限されます。

デジタル署名

公開キー アルゴリズムを使用して、デジタル署名を形成することもできます。 デジタル署名は、送信者の ID を認証し (送信者の公開キーを信頼している場合)、データの整合性を保護するのに役立ちます。 Alice によって生成された公開キーを使用して、Alice のデータの受信者は、デジタル署名と Alice のデータと Alice の公開キーを比較することで、Alice が送信したことを確認できます。

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

送信者の公開キーは一般的な知識であり、通常はデジタル署名形式に含まれているため、署名はだれでも検証できます。 このメソッドは、メッセージの秘密を保持しません。メッセージをシークレットにするには、暗号化する必要もあります。

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

ハッシュ値

ハッシュ アルゴリズムは、任意の長さのバイナリ値を、ハッシュ値と呼ばれる固定長の小さいバイナリ値にマップします。 ハッシュ値は、データの一部の数値表現です。 プレーンテキストの段落をハッシュし、段落の 1 文字でも変更すると、後続のハッシュによって異なる値が生成されます。 ハッシュが暗号的に強力な場合、その値は大幅に変更されます。 たとえば、メッセージの 1 ビットが変更された場合、強力なハッシュ関数によって 50% 異なる出力が生成される場合があります。 多くの入力値が同じ出力値にハッシュされる場合があります。 ただし、同じ値にハッシュする 2 つの個別の入力を見つけることは、計算上不可能です。

2 つのパーティ (Alice と Bob) は、ハッシュ関数を使用してメッセージの整合性を確保できます。 メッセージに署名するハッシュ アルゴリズムを選択します。 Alice はメッセージを書き込み、選択したアルゴリズムを使用してそのメッセージのハッシュを作成します。 その後、次のいずれかの方法に従います。

  • Alice は、プレーンテキスト メッセージとハッシュメッセージ (デジタル署名) を Bob に送信します。 Bob はメッセージを受信してハッシュし、そのハッシュ値と Alice から受信したハッシュ値を比較します。 ハッシュ値が同一の場合、メッセージは変更されませんでした。 値が同一でない場合、Alice がメッセージを書き込んだ後にメッセージが変更されました。

    残念ながら、この方法では送信者の信頼性は確立されません。 誰でも Alice を偽装し、Bob にメッセージを送信できます。 同じハッシュ アルゴリズムを使用してメッセージに署名できます。すべての Bob は、メッセージがその署名と一致することを判断できます。 これは、中間者攻撃の 1 つの形式です。 詳細については、「 暗号化の次世代 (CNG) セキュリティで保護された通信の例」を参照してください。

  • Alice は、セキュリティで保護されていないパブリック チャネル経由でプレーンテキスト メッセージを Bob に送信します。 彼女は、セキュリティで保護されたプライベート チャネル経由で Bob にハッシュされたメッセージを送信します。 Bob はプレーンテキスト メッセージを受信し、ハッシュし、プライベートに交換されたハッシュとハッシュを比較します。 ハッシュが一致する場合、Bob は次の 2 つのことを認識します。

    • メッセージは変更されませんでした。

    • メッセージの送信者 (Alice) は本物です。

    このシステムを機能させるには、Alice は Bob を除くすべての関係者から元のハッシュ値を非表示にする必要があります。

  • Alice は、セキュリティで保護されていないパブリック チャネル経由でプレーンテキスト メッセージを Bob に送信し、ハッシュされたメッセージをパブリックに表示可能な Web サイトに配置します。

    このメソッドは、誰かがハッシュ値を変更できないようにすることで、メッセージの改ざんを防ぎます。 メッセージとそのハッシュはだれでも読み取ることができますが、ハッシュ値は Alice によってのみ変更できます。 Alice を偽装する攻撃者は、Alice の Web サイトにアクセスする必要があります。

前の方法では、Alice のメッセージがプレーンテキストで送信されるため、誰かが Alice のメッセージを読むのを妨げるものはありません。 完全なセキュリティには、通常、デジタル署名 (メッセージ署名) と暗号化が必要です。

.NET には、ハッシュ アルゴリズムを実装する次のクラスが用意されています。

.NET では、 MD5SHA1も提供されます。 ただし、MD5 アルゴリズムと SHA-1 アルゴリズムは安全でなく、代わりに SHA-2 が推奨されるようになりました。 SHA-2 には、SHA256、SHA384、SHA512 が含まれています。

乱数の生成

乱数の生成は、多くの暗号化操作に不可欠です。 たとえば、暗号化キーを再現するには、可能な限りランダムである必要があります。 暗号乱数ジェネレーターは、半分より優れた確率で予測するために計算不可能な出力を生成する必要があります。 したがって、次の出力ビットを予測する方法は、ランダムな推測よりも優れたパフォーマンスを発揮してはなりません。 .NET のクラスは、乱数ジェネレーターを使用して暗号化キーを生成します。

RandomNumberGenerator クラスは、乱数ジェネレーター アルゴリズムの実装です。

ClickOnce マニフェスト

次の暗号化クラスを使用すると、 ClickOnce テクノロジを使用して配置されるアプリケーションのマニフェスト署名に関する情報を取得して確認できます。

さらに、次のクラスは特定のシグネチャ情報を提供します。

暗号化次世代 (CNG) クラス

Cryptography Next Generation (CNG) クラスは、ネイティブ CNG 関数のマネージド ラッパーを提供します。 (CNG は CryptoAPI の代わりです)。)これらのクラスは、名前の一部として "Cng" を持ちます。 CNG ラッパー クラスの中心となるのは、CNG キーのストレージと使用を抽象化する CngKey キー コンテナー クラスです。 このクラスを使用すると、キー ペアまたは公開キーを安全に格納し、単純な文字列名を使用して参照できます。 楕円曲線ベースの ECDsaCng シグネチャ クラスと ECDiffieHellmanCng 暗号化クラスでは、 CngKey オブジェクトを使用できます。

CngKey クラスは、キーの開き、作成、削除、エクスポートなど、さまざまな追加操作に使用されます。 また、ネイティブ関数を直接呼び出すときに使用する基になるキー ハンドルへのアクセスも提供します。

.NET には、次のようなさまざまなサポート CNG クラスも含まれています。

  • CngProvider はキー ストレージ プロバイダーを保持します。

  • CngAlgorithm は CNG アルゴリズムを維持します。

  • CngProperty では、頻繁に使用されるキー プロパティが保持されます。

こちらも参照ください