これは、タイトルが示すように、ダミーのための.NETでの暗号化の簡単な紹介です。 シンプルなものがあり、詳細な知識はありません。
ハッシュについて少し
ハッシュとは、任意の長さの入力データを固定長のバイト配列に変換するプロセスです。
ハッシュは一方向の変換関数であり、元の入力データを取得するために結果を逆にすることはできません。 パスワードの保存によく使用されます。 攻撃者がハッシュを受け取ったとしても、パスワード自体を取得することはできません。 ハッシュの長さは、ハッシュアルゴリズムによって決定されます。
.NETでは、次のハッシュアルゴリズムを見つけることができます(HashAlgorithm抽象クラスから継承)。
- MD5-128ビット長
- SHA(セキュアハッシュアルゴリズム)-そのようなクラスはありませんが、SHA1(160ビット)、SHA256、SHA384、SHA512があります
- KeydHashAlgorithm(メッセージ認証コードとして知られています)。 代表は、 HMACおよびMACTripleDESアルゴリズムのクラスです
.NETでは、キーベースのハッシュが必要ない場合、今日ceteris paribus、SHA512アルゴリズムを使用するのが最善です。 MD5はやや時代遅れで、侵害される可能性があります。 SHA512は非常に高速です(SHA1に次いで2番目)。 実際、SHAファミリ全体は高速です。 最も遅いMACTripleDES。 HMACファミリは、SHAの約2〜4倍遅いです。
キーベースのハッシュを使用して、データを変更から保護できます。 クライアントからサーバーに送信されたリクエストは、変更を確認できます。 サーバーに送信されるデータが変更されている場合、ハッシュは一致しません。 文字列クエリを保護する場合、キーなしで単純なハッシュを使用することはできません。 なぜなら、攻撃者は考えられるすべてのハッシュアルゴリズムを単に並べ替え、必要なものを見つけ、クエリ文字列の引数を変更し、目的のハッシュに置き換えるだけで、サーバーは正しく形成された要求に応答する以外に選択肢がないからです。 そのような保護のために、HMACSHA1はキーベースのハッシュアルゴリズムとして適しているかもしれません。 もちろん、秘密鍵の保存の問題もその潜在能力を最大限に発揮します。
public static byte[] ComputeHmacsha1(byte[] data, byte[] key) { using (var hmac = new HMACSHA1(key)) { return hmac.ComputeHash(data); } }
キーを見つけるために、攻撃者が後続の列挙のために入力データとそれに対応するハッシュを収集する機会が少なくなるように、ソルトを追加できます。
ソルトは、暗号化にエントロピーを追加するランダム化された追加の「キー」です。 塩は平文で転送できます。 Saltを生成し、現在のユーザーセッションに関連付けることができます。 したがって、saltはすべてのセッションを変更し、同じリクエストのハッシュ結果は異なります。 また、特に攻撃者がハッシュ値にアクセスできる場合は特に、パスワードをハッシュして辞書検索を複雑にするときにもソルトが追加されます。 ソルトを生成するには、タイプRNGCryptoServiceProviderの暗号ジェネレーターを使用することをお勧めします。
ソルトは次のように生成できます。
string salt = GenSalt(32); string GenSalt(int length) { RNGCryptoServiceProvider p = new RNGCryptoServiceProvider(); var salt = new byte[length]; p.GetBytes(salt); return Convert.ToBase64String(salt); }
対称暗号化アルゴリズムについて少し
.NETは、SymmetricAlgorithmの基本クラスを継承するいくつかのアルゴリズムを提供します。
- レインダール
- DES
- トリプルデス
- RC2
現在、.NETで推奨される対称アルゴリズムはRijndaelです。 Mars、RC6、Serpent、TwoFishも優れていますが、.NETには実装されていません。 サードパーティのライブラリのみの場合。 Rijndaelはブロック暗号アルゴリズムです。
ブロックは、入力データがブロックに分割され、暗号化アルゴリズムがこれらの各ブロックに順番に適用されることを意味します。
パディングとは、結果として目的のサイズを取得するために、ブロック暗号化の結果を「完了する」プロセスを意味します。
Rijndaelはいくつかのパディングモードをサポートしています-ゼロで仕上げる、ランダムな値で仕上げる、いくつかのモードです。 おそらく、エントロピーを追加する最も信頼できる方法は、値をランダム化することです-これはISO10126モードです。
Rijndaelは、ブロックを操作するいくつかの方法もサポートしています。 デフォルトでは、CBCモードを選択することをお勧めします。これは、次のブロックの暗号化によって前のブロックの暗号化の結果も得られることを意味し、エントロピーが再び増加します。
IV-初期化ベクトル。 最初のブロックの暗号化を入力にフィードする必要がありました。 Rijndaelを使用すると、自動的に生成されます。 復号化の場合、初期化ベクトルを知っている必要があり、クリアテキストで送信できます。
小さな例:
string Encrypt() { RijndaelManaged cipher = new RijndaelManaged(); cipher.KeySize = 256; cipher.BlockSize = 256; // 128 AES cipher.Padding = PaddingMode.ISO10126; cipher.Mode = CipherMode.CBC; cipher.Key = "some_super_secret_key"; ICryptoTransform t = cipher.CreateEncryptor(); string text = "some_text_to_encrypt"; byte[] textInBytes = Encoding.UTF8.GetBytes(text); byte[] result = t.TransformFinalBlock(textInBytes, 0, textInBytes.Length); return Convert.ToBase64String(result); }
.NETには興味深いCryptoStreamクラスもあります。 FileStreamなどのストリームと暗号化を統合するように設計されています。 たとえば、暗号化を実行する1つのCryptoStreamに、FileStreamを含む別のCryptoStreamを埋め込むことができます。 次に、最初のCryptoStreamで書き込みを行い、テキストを転送し、その結果、特定のファイルに書き込まれた暗号化されたテキストを取得します。
非対称暗号化アルゴリズムについて少し
非対称アルゴリズムの場合、公開鍵は暗号化に使用され、秘密鍵は復号化に使用されます。 暗号化されたメッセージが参加者の1人のみによって復号化される場合、秘密鍵は1か所にのみ保存できます。 対称暗号化の場合、秘密鍵をすべてのメッセージング参加者に知らせる必要があります。
非対称暗号化アルゴリズムは、対称暗号化よりも約100〜1000倍遅いです。 したがって、それらを使用して大量のデータを暗号化すると、費用がかかる可能性があります。 非対称暗号化は対称と併用できます。 非対称暗号化は、データの暗号化に使用されるセッションキーを生成します。
次の基本的なアルゴリズムが.NETに実装されています。
- RSA
- DSA(デジタル署名のみ)
- ECDiffieHellman
通常、RSAキーの長さは1024、2048、4096ビットです。 長さが1024のキーのRSAは信頼できないことが証明されているため、より長いキーを使用する必要があります。
RSAの使用例:
public class RsaWithCspKey { const string ContainerName = "MyContainer"; public void AssignNewKey() { CspParameters cspParams = new CspParameters(1); cspParams.KeyContainerName = ContainerName; cspParams.Flags = CspProviderFlags.UseMachineKeyStore; cspParams.ProviderName = "Microsoft Strong Cryptographic Provider"; var rsa = new RSACryptoServiceProvider(cspParams) { PersistKeyInCsp = true }; } public void DeleteKeyInCsp() { var cspParams = new CspParameters { KeyContainerName = ContainerName }; var rsa = new RSACryptoServiceProvider(cspParams) { PersistKeyInCsp = false }; rsa.Clear(); } public byte[] EncryptData(byte[] dataToEncrypt) { byte[] cipherbytes; var cspParams = new CspParameters { KeyContainerName = ContainerName }; using (var rsa = new RSACryptoServiceProvider(2048, cspParams)) { cipherbytes = rsa.Encrypt(dataToEncrypt, false); } return cipherbytes; } public byte[] DecryptData(byte[] dataToDecrypt) { byte[] plain; var cspParams = new CspParameters { KeyContainerName = ContainerName }; using (var rsa = new RSACryptoServiceProvider(2048, cspParams)) { plain = rsa.Decrypt(dataToDecrypt, false); } return plain; } }
デジタル署名は、非対称暗号化に基づいています。 デジタル署名は、メッセージのプライバシーを保証し、メッセージが1人または別の作成者に属していることを証明します。 通常、これは次のように機能します。
1.アリスはメッセージを暗号化します。
2.アリスはメッセージのハッシュを取得します。
3.アリスは署名用の秘密鍵でメッセージに署名します。
4.アリスは暗号化されたデータ、ハッシュ、署名をボブに送信します。
5.ボブは、暗号化されたデータのハッシュを計算します。
6.ボブは公開鍵を使用して署名を検証します。
署名の使用例:
public class DigitalSignature { private RSAParameters _publicKey; private RSAParameters _privateKey; public void AssignNewKey() { using (var rsa = new RSACryptoServiceProvider(2048)) { rsa.PersistKeyInCsp = false; _publicKey = rsa.ExportParameters(false); _privateKey = rsa.ExportParameters(true); } } public byte[] SignData(byte[] hashOfDataToSign) { using (var rsa = new RSACryptoServiceProvider(2048)) { rsa.PersistKeyInCsp = false; rsa.ImportParameters(_privateKey); var rsaFormatter = new RSAPKCS1SignatureFormatter(rsa); rsaFormatter.SetHashAlgorithm("SHA256"); return rsaFormatter.CreateSignature(hashOfDataToSign); } } public bool VerifySignature(byte[] hashOfDataToSign, byte[] signature) { using (var rsa = new RSACryptoServiceProvider(2048)) { rsa.ImportParameters(_publicKey); var rsaDeformatter = new RSAPKCS1SignatureDeformatter(rsa); rsaDeformatter.SetHashAlgorithm("SHA256"); return rsaDeformatter.VerifySignature(hashOfDataToSign, signature); } } }
この記事は、Pluralsightの2つのコース、 「 。 NETの暗号化 入門」と「.NETの実用暗号化 」の非常に短い要約です。
翻訳はこちらです。