Я использую следующий (урезанный) класс для шифрования некоторых данных перед отправкой их из приложения iPad в веб-службу WCF.
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 на сервере, часть расшифрованной строки - это бред .Зашифрованные результаты с сервера расшифровываются правильно.
Проблема не проявляется, если я создаю новый экземпляр 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
имеет недостатки?Или здесь есть какие-то подводные камни в управлении потоками и памятью, не связанные с этим примером криптографии?
PS: я проверил это на iPad и iPad Simulator;оба показывают это странное поведение.