Почему я не могу зашифровать несколько строк с помощью одного шифратора на MonoTouch?

Я использую следующий (урезанный) класс для шифрования некоторых данных перед их отправкой из приложения 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 некорректным? Или здесь присутствуют некоторые подводные камни управления потоком и памятью в MonoTouch, не связанные с этим примером криптографии?

P.S .: Я тестировал это как на iPad, так и на iPad Simulator; оба демонстрируют это странное поведение.

5
задан poupou 27 September 2011 в 21:19
поделиться