web-dev-qa-db-ja.com

'System.Security.Cryptography.AesManaged'を使用してbyte []を暗号化する方法は?

基本的に、System.Security.Cryptography.AesManaged(または、あると思われる場合はより良いクラス)を使用して、特定の対称鍵を使用して1つのバイト配列を取得し、別の暗号化されたバイト配列を作成します(必要になると思います) 1?)。

また、この手順を逆にする方法も必要になります。

これのポイントは、保存されているパスワードを暗号化できるようにすることです。これを行う簡単な方法があると思いますか?

ありがとう

13
Chris

マイケルの答え(の古いバージョン)に触発されて、私が最終的にしたことは次のとおりです。

private string Encrypt(string input)
{
  return Convert.ToBase64String(Encrypt(Encoding.UTF8.GetBytes(input)));
}
private byte[] Encrypt(byte[] input)
{
  PasswordDeriveBytes pdb = new PasswordDeriveBytes("hjiweykaksd", new byte[] { 0x43, 0x87, 0x23, 0x72, 0x45, 0x56, 0x68, 0x14, 0x62, 0x84 });
  MemoryStream ms = new MemoryStream();
  Aes aes = new AesManaged();
  aes.Key = pdb.GetBytes(aes.KeySize / 8);
  aes.IV = pdb.GetBytes(aes.BlockSize / 8);
  CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write);
  cs.Write(input, 0, input.Length);
  cs.Close();
  return ms.ToArray();
}
private string Decrypt(string input)
{
  return Encoding.UTF8.GetString(Decrypt(Convert.FromBase64String(input)));
}
private byte[] Decrypt(byte[] input)
{
  PasswordDeriveBytes pdb = new PasswordDeriveBytes("hjiweykaksd", new byte[] { 0x43, 0x87, 0x23, 0x72, 0x45, 0x56, 0x68, 0x14, 0x62, 0x84 });
  MemoryStream ms = new MemoryStream();
  Aes aes = new AesManaged();
  aes.Key = pdb.GetBytes(aes.KeySize / 8);
  aes.IV = pdb.GetBytes(aes.BlockSize / 8);
  CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write);
  cs.Write(input, 0, input.Length);
  cs.Close();
  return ms.ToArray();
}
12
Chris

編集:eed3si9nの編集に気づきました...私は同意します、対称暗号化はパスワードには悪い選択です。代わりにハッシュ(およびnotMD5)を使用してください。これが 非常に完全な例です

簡単な例:

byte[] clear = GetCleartext();
HashAlgorithm sha2 = SHA256CryptoServiceProvider.Create();
byte[] hashed = sha2.ComputeHash(clear);

正しいパスワードを検証するには、提供されたパスワードに対して同じ計算を実行し、その結果をデータベースにあるハッシュと比較します。

レインボーテーブル攻撃 を回避するために、クリアテキストにソルト(ランダムデータ)を追加することをお勧めします。基本的に、ハッシュする前に、そのユーザーに固有の既知のランダムに生成された値をクリアテキストに追加します。

12

C#でのデータの単純な暗号化と復号化

Edit:パスワードについては、本当に回復する必要がない限り、双方向暗号化を行う代わりに BCrypt を使用することをお勧めします元のパスワード。通常、必要なのは、パスワード自体ではなく、誰かがパスワードを知っているという事実だけです。

8
Eugene Yokota

http://www.superstarcoders.com/blogs/posts/symmetric-encryption-in-c-sharp.aspx には、対称鍵暗号化の非常に優れたC#実装があります。 AES、Triple DES、およびRijndaelをサポートします。次の形式で関数を簡単にたどることができます。

 string Encrypt(string plaintext, string password, string salt)
2
Walter Stabosz

OPは、資格情報を別のサービスに渡す必要があると述べています。これは、パスワードの保存と検証とはまったく異なる問題です。

パートナーサービスをどの程度制御できるか、またはパートナーサービスが何を公開するかに応じて、最適なソリューションには、ベンダーが提供するアプローチ、またはKerberos、SAML、その他の安定した安全なベアラートークン手段などの業界標準のアプローチが含まれます。これは深いトピックです。

ただし、基本認証SSL/TLSを介して資格情報を渡す必要があると仮定しましょう。だから今、あなたはそれらを可逆的な方法で安全に保管する必要があります。この問題を解決するために、証明書の秘密鍵を使用して秘密鍵を伝達することに成功しました。これにより、オペレーティングシステムによる秘密の保護が可能になり、OPS担当者がキーを管理できるようになります。これは望ましいことです。プロセスの実行に使用されるアカウントには、秘密鍵を表示する権限が付与されている必要があります。秘密鍵は、OSでの信頼チェーンを終了します。

それでもキーローテーションについて考える必要があるかもしれません。そのため、暗号文とともにバージョン番号を保存する必要があります。

また、SecureStringも興味深いかもしれませんが、すべての.NET APIがSecureStringを資格情報の一部として渡すことを許可するまで、多くの場合、管理ヒープ上に文字列が表示され、破棄できません。

とにかく、これはコードによるスプーンフィードの答えではありませんが、経験から、秘密のチェーンの管理は常に問題であり、Active Directoryなどの強化されたインフラストラクチャで終了できない場合は、証明書が次善の策であることがわかりました事。

0
bkrakower