簡単な文字列の暗号化が必要だったので、以下のコードを書きました(こちらから大いに"inspire"されました)。
// create and initialize a crypto algorithm
private static SymmetricAlgorithm getAlgorithm(string password) {
SymmetricAlgorithm algorithm = Rijndael.Create();
Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(
password, new byte[] {
0x53,0x6f,0x64,0x69,0x75,0x6d,0x20, // salty goodness
0x43,0x68,0x6c,0x6f,0x72,0x69,0x64,0x65
}
);
algorithm.Padding = PaddingMode.ISO10126;
algorithm.Key = rdb.GetBytes(32);
algorithm.IV = rdb.GetBytes(16);
return algorithm;
}
/*
* encryptString
* provides simple encryption of a string, with a given password
*/
public static string encryptString(string clearText, string password) {
SymmetricAlgorithm algorithm = getAlgorithm(password);
byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, algorithm.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
return Convert.ToBase64String(ms.ToArray());
}
/*
* decryptString
* provides simple decryption of a string, with a given password
*/
public static string decryptString(string cipherText, string password) {
SymmetricAlgorithm algorithm = getAlgorithm(password);
byte[] cipherBytes = Convert.FromBase64String(cipherText);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, algorithm.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
return System.Text.Encoding.Unicode.GetString(ms.ToArray());
}
このコードは正常に動作しているように見えますが、不正なキーを使用してデータを復号化すると、decryptString の cs.Close() 行で CryptographicException - "Padding is invalid and cannot be removed" - を受け取ります。
のコード例です。
string password1 = "password";
string password2 = "letmein";
string startClearText = "The quick brown fox jumps over the lazy dog";
string cipherText = encryptString(startClearText, password1);
string endClearText = decryptString(cipherText, password2); // exception thrown
私の質問は、これは予想されることなのでしょうか?私は、間違ったパスワードで復号化すると、例外ではなく、無意味な出力になると思っていました。
すでに回答されていることですが、「なぜ」そうなるのかを説明するのがよいと思います。
パディングスキームは通常、ほとんどの暗号フィルタが意味的に安全ではないため、ある種のクリプトアタックを防止するために適用されます。例えば、RSAでは通常OAEPというパディング方式が使われ、ある種の攻撃(選択平文攻撃やblindingなど)を防ぐことができます。
パディング方式は、メッセージが送信される前に、メッセージmに何らかの(通常は)ランダムなゴミを付加するものです。例えば、OAEP方式では、2つのオラクルが使用されます(これは単純化された説明です)。
1.1. モジュラスのサイズが与えられたら、k1ビットを0に、k0ビットを乱数にパディングします。 2.2.メッセージに何らかの変換を施し、パディングされたメッセージを得て、暗号化して送信する。
これにより、メッセージのランダム化と、メッセージがゴミであるかどうかをテストする方法が得られます。パディング方式は可逆的なので、メッセージを復号化するとき、メッセージ自体の完全性については何も言えませんが、パディングについては何らかの主張ができます。