在将数据从 iPad 应用程序发送到 WCF Web 服务之前,我正在使用以下(精简的)类来加密一些数据。
public class FlawedAlgorithm
{
protected static byte[] key = { 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42 };
protected static byte[] vector = { 13, 37, 13, 37, 13, 37, 13, 37, 13, 37, 13, 37, 13, 37, 13, 37 };
protected ICryptoTransform encryptor, decryptor;
protected UTF8Encoding encoder;
public FlawedAlgorithm()
{
using (var rijndael = new RijndaelManaged())
{
this.encryptor = rijndael.CreateEncryptor(key, vector);
this.decryptor = rijndael.CreateDecryptor(key, vector);
}
this.encoder = new UTF8Encoding();
}
public string Encrypt(string unencrypted)
{
var buffer = this.encoder.GetBytes(unencrypted);
return Convert.ToBase64String(Encrypt(buffer));
}
public string Decrypt(string encrypted)
{
var buffer = Convert.FromBase64String(encrypted);
return this.encoder.GetString(Decrypt(buffer));
}
private byte[] Encrypt(byte[] buffer)
{
var encryptStream = new MemoryStream();
using (var cryptoStream = new CryptoStream(encryptStream, this.encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(buffer, 0, buffer.Length);
}
return encryptStream.ToArray();
}
private byte[] Decrypt(byte[] buffer)
{
var decryptStream = new MemoryStream();
using (var cryptoStream = new CryptoStream(decryptStream, this.decryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(buffer, 0, buffer.Length);
}
return decryptStream.ToArray();
}
}
当我在服务器和 iPad 上运行以下代码时,都打印相同的加密字符串。
var algorithm = new FlawedAlgorithm();
Console.WriteLine(algorithm.Encrypt("Some string"));
但是,当我尝试加密第二个值时,服务器和 iPad 上的结果是不同的。
var algorithm = new FlawedAlgorithm();
// The first encryption still functions correctly.
Console.WriteLine(algorithm.Encrypt("Some string"));
// This second encryption produces a different value on the iPad.
Console.WriteLine(algorithm.Encrypt("This text is a bit longer"));
当我在服务器上解密偏离的 iPad 结果时,解密字符串的一部分是 gibberish。来自服务器的加密结果正确解密。
FlawedAlgorithm
如果我为每个调用创建一个新实例,问题就不会显现出来,例如:
// These statements produce the correct results on the iPad.
Console.WriteLine(new FlawedAlgorithm().Encrypt("Some string"));
Console.WriteLine(new FlawedAlgorithm().Encrypt("This text is a bit longer"));
这使我认为问题出在所涉及对象的状态中。我检查了方法中的buffer
变量,实例Encrypt(string)
产生的值是正确的。UTF8Encoding
这意味着该encryptor
领域(或其底层实现)是罪魁祸首。
当我开始改变第一个加密值的大小时,我可以看到第二个加密调用结果的变化。这可能意味着流的某些部分没有被正确清除或覆盖。但是FlawedAlgorithm
该类使用的流不是其状态的一部分;它们在每次方法调用时重新创建。而且该encryptor
对象看起来不像管理自己的流的类型。
有没有其他人遇到过类似的问题?RijndaelManaged
班级有问题吗?或者 MonoTouch 中是否存在一些流和内存管理缺陷,与这个密码学示例无关?
PS:我已经在 iPad 和 iPad Simulator 上测试过了;两者都表现出这种奇怪的行为。