2010-12-30 4 views
0

私はこのコードをAES暗号化に使用していますが、このコードが良くて間違っていないことを確認できる人もいますか?それは正常に動作しますが、私はアルゴリズムの実装についてより心配しています。C#で自分のAES暗号化コードを改善する方法はありますか?

// Plaintext value to be encrypted. 

//Passphrase from which a pseudo-random password will be derived. 
//The derived password will be used to generate the encryption key. 

//Password can be any string. In this example we assume that this passphrase is an ASCII string. 

//Salt value used along with passphrase to generate password. 
//Salt can be any string. In this example we assume that salt is an ASCII string. 

//HashAlgorithm used to generate password. Allowed values are: "MD5" and "SHA1". 
//SHA1 hashes are a bit slower, but more secure than MD5 hashes. 

//PasswordIterations used to generate password. One or two iterations should be enough. 

//InitialVector (or IV). This value is required to encrypt the first block of plaintext data. 
//For RijndaelManaged class IV must be exactly 16 ASCII characters long. 

//KeySize. Allowed values are: 128, 192, and 256. 
//Longer keys are more secure than shorter keys. 

//Encrypted value formatted as a base64-encoded string. 


public static string Encrypt(string PlainText, string Password, string Salt, string HashAlgorithm, int PasswordIterations, string InitialVector, int KeySize) 
{ 
    byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector); 
    byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt); 
    byte[] PlainTextBytes = Encoding.UTF8.GetBytes(PlainText); 
    PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations); 
    byte[] KeyBytes = DerivedPassword.GetBytes(KeySize/8); 
    RijndaelManaged SymmetricKey = new RijndaelManaged(); 
    SymmetricKey.Mode = CipherMode.CBC; 
    ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes); 
    MemoryStream MemStream = new MemoryStream(); 
    CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write); 
    CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length); 
    CryptoStream.FlushFinalBlock(); 
    byte[] CipherTextBytes = MemStream.ToArray(); 
    MemStream.Close(); 
    CryptoStream.Close(); 
    return Convert.ToBase64String(CipherTextBytes); 
} 

public static string Decrypt(string CipherText, string Password, string Salt, string HashAlgorithm, int PasswordIterations, string InitialVector, int KeySize) 
{ 
    byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector); 
    byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt); 
    byte[] CipherTextBytes = Convert.FromBase64String(CipherText); 
    PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations); 
    byte[] KeyBytes = DerivedPassword.GetBytes(KeySize/8); 
    RijndaelManaged SymmetricKey = new RijndaelManaged(); 
    SymmetricKey.Mode = CipherMode.CBC; 
    ICryptoTransform Decryptor = SymmetricKey.CreateDecryptor(KeyBytes, InitialVectorBytes); 
    MemoryStream MemStream = new MemoryStream(CipherTextBytes); 
    CryptoStream cryptoStream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read); 
    byte[] PlainTextBytes = new byte[CipherTextBytes.Length]; 
    int ByteCount = cryptoStream.Read(PlainTextBytes, 0, PlainTextBytes.Length); 
    MemStream.Close(); 
    cryptoStream.Close(); 
    return Encoding.UTF8.GetString(PlainTextBytes, 0, ByteCount); 
} 

私はプロのセキュリティの男やプロのプログラマーではないよ、私は学習を開始し、私はそれを

私の計画を理解するのが大好きですが、まだ次の規格を、最小限の入力を必要とAES暗号化機能を構築することですPHPやJavaScriptのような他の言語で同等の機能を実現するのは簡単です!

ありがとうございました

答えて

3

いくつかの一般的なコメント。最初はIVの周りです。一般的には、IVをランダムにします。これを(表示可能な)ASCIIに制限することによって、可能な値をいくらか制限しています。一般的には、a)GenerateIV()メソッドを使用し、b)暗号文にIV値を付加して、c)関数のいずれかのパラメータとして渡す必要はありません。

2番目のコメントは、一般的に、暗号のニーズに対する将来の変更を計画する必要があるということです。いくつかのバージョニングやパラメータ情報を暗号文とともに埋め込み、特定の暗号設定をコードに埋め込まないようにしてください。後でパスワードの反復回数を2倍にすると決めた場合など、以前の設定を使用して暗号化された値を復号化する(または値にアクセスできないという警告をユーザーに表示する)場合があります。

また、多くの決定を設定ファイルにプッシュすることもできます。たとえば、今日RijndaelManagedにマップするcreate a name for your cryptoプロバイダ(MyAppSymmetricCryptoなど)を、後で適切なものに変更することができます。

MS答える@Damien_The_Unbelieverするaddidtionで

+0

また、IVに関するコメントも塩のために保持されています。 –

+0

ありがとうございます。私はあなたの提案をコードにどのように翻訳していますか? –

2

Rfc2898DeriveBytes代わりのPasswordDeriveBytesを使用することをお勧めします。 (そして、メソッドパラメータから 'HashAlgorithm'を削除することができます)。

あなたのパスワードからIVを計算することができます。

var bytes = new Rfc2898DeriveBytes(password, salt, iterations); 
var key = bytes.GetBytes(keySize); 
var iv = bytes.GetBytes(ivSize); 

無効な値/範囲のために、あなたの入力値をチェックする必要があります。

& CryptoStreamクラスをusing文で囲みます。

+0

同じパスワードを両方のメッセージに使用していても、複数のメッセージに同じIVを使用することは個人的にはお勧めしません。同じIV +同じキーは、2つのメッセージが同じ(N =ブロックサイズ)バイトで始まるかどうかを示します。これは意味のある開示であるかもしれないし、そうでないかもしれないが、一般的な暗号ソリューションは避けるべきである。 –

+0

ありがとうございます。私はあなたの提案をコードにどのように翻訳していますか? –

+0

私はvar iv = bytes.GetBytes(ivSize)を意味します。 "iv"は私のコードの "InitialVectorBytes"ですか?それは私のコードのどこに "ivSize"ですか? –

関連する問題