暗号化の問題について報告するために書いています。RijndaelManaged
のクラスを使用すると問題が発生しSystem.Security.Cryptography
ます。RijndaelManaged
パディングなしでCFB-8
(FeedbackSize = 8) モードで使用することが重要です( PaddingMode.None
)。このような設定により、暗号化されたデータのサイズと復号化されたデータのサイズが等しくなります。
残念ながら、Mono (MVS2010 IDE v2.0.8152 用の Mono コンパイラ) でコンパイルされたコードは、データ暗号化で例外をスローし、次のメッセージが表示されます。
[Unhandled Exception: System.Security.Cryptography.CryptographicException: invalid block length at Mono.Security.Cryptography.SymmetricTransform.FinalEncrypt].
ネイティブの Visual Studio 2010 コンパイラを使用して、Windows XP および Windows 7 で .NET Framework 4.0 をテストしました。ネイティブの Microsoft .NET コンパイラは例外をスローせず、コード例はうまく機能することがわかりました。
以下に 2 つの例 (Repro コード) を貼り付けました。1 つは例外をスローする Mono 用で、もう 1 つはネイティブ C# コンパイラ用で、この場合例外はありません。また、コードをテストするためのオンライン コンパイラへのリンクも貼り付けました。
Mono コンパイラがこの例外をスローするのはなぜですか?
Mono コード サンプル (テスト用オンライン コンパイラ、Compile Online )
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
namespace Dela.Mono.Examples
{
public class HelloWorld
{
public static void Main(string[] args)
{
string plainText = "This will be encrypted.";
string plainText2 = "";
RijndaelManaged aesAlg = new RijndaelManaged();
aesAlg.BlockSize = 128;
aesAlg.KeySize = 256;
aesAlg.Mode = CipherMode.CFB;
aesAlg.FeedbackSize = 8;
aesAlg.Padding = PaddingMode.None;
aesAlg.GenerateKey();
aesAlg.GenerateIV();
ICryptoTransform encryptor = aesAlg.CreateEncryptor();
MemoryStream msEncrypt = new MemoryStream();
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) {
swEncrypt.Write(plainText);
}
}
Console.WriteLine(msEncrypt.ToArray().Length);
Console.WriteLine(System.Text.Encoding.UTF8.GetString(msEncrypt.ToArray()));
byte[] customArray = msEncrypt.ToArray();
ICryptoTransform decryptor = aesAlg.CreateDecryptor();
MemoryStream msDecrypt = new MemoryStream(customArray);
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {
using (StreamReader swDecrypt = new StreamReader(csDecrypt)) {
plainText2 = swDecrypt.ReadToEnd();
}
}
Console.WriteLine(plainText2.Length);
Console.WriteLine(plainText2);
}
}
}
ネイティブ C# コード サンプル (テスト用オンライン コンパイラ、Compile Online )
// Rextester.Program.Main is the entry point for your code. Don't change it.
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
namespace Rextester
{
public class Program
{
public static void Main(string[] args)
{
string plainText = "This will be encrypted.";
string plainText2 = "";
RijndaelManaged aesAlg = new RijndaelManaged();
aesAlg.BlockSize = 128;
aesAlg.KeySize = 256;
aesAlg.Mode = CipherMode.CFB;
aesAlg.FeedbackSize = 8;
aesAlg.Padding = PaddingMode.None;
aesAlg.GenerateKey();
aesAlg.GenerateIV();
ICryptoTransform encryptor = aesAlg.CreateEncryptor();
MemoryStream msEncrypt = new MemoryStream();
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) {
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)) {
swEncrypt.Write(plainText);
}
}
Console.WriteLine(msEncrypt.ToArray().Length);
Console.WriteLine(System.Text.Encoding.UTF8.GetString(msEncrypt.ToArray()));
byte[] customArray = msEncrypt.ToArray();
ICryptoTransform decryptor = aesAlg.CreateDecryptor();
MemoryStream msDecrypt = new MemoryStream(customArray);
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) {
using (StreamReader swDecrypt = new StreamReader(csDecrypt)) {
plainText2 = swDecrypt.ReadToEnd();
}
}
Console.WriteLine(plainText2.Length);
Console.WriteLine(plainText2);
}
}
}