Криптография С# .NET неправильно расшифровывает

Я пытаюсь зашифровать и расшифровать текст на С# (.NET 3.5), выясняя, что этот простой код не работает:

    private const string KEY = "Chiave";

    static void Main(string[] args)
    {

        string plainText = "Data to be encrypted";

        byte[] keyArray;
        MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
        keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(KEY));

        byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(plainText);

        TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
        tdes.Key = keyArray;
        tdes.Mode = CipherMode.CBC;
        tdes.Padding = PaddingMode.PKCS7;

        ICryptoTransform cTransform = tdes.CreateEncryptor();
        byte[] encArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

        tdes = new TripleDESCryptoServiceProvider();
        tdes.Key = keyArray;
        tdes.Mode = CipherMode.CBC;
        tdes.Padding = PaddingMode.PKCS7;

        cTransform = tdes.CreateDecryptor();
        byte[] decArray = cTransform.TransformFinalBlock(encArray, 0, encArray.Length);

        if (encArray.Length == decArray.Length)
        {
            for (int i = 0; i < encArray.Length; ++i)
                Console.Out.Write("{0,3}|{1,3}", encArray[i], decArray[i]);
        } else
            Console.Out.Write("Length error!");

        Console.In.Read();
    }

Кажется, что фаза шифрования или дешифрования искажает некоторые байты в начале текста (по-разному каждый раз, когда я запускаю программу), иногда меняя даже длину массива байтов. Мне удалось заставить его работать с помощью шифра ECB, но мои данные содержат несколько статических блоков, что в любое время приводит к одному и тому же результату.

Из https://msdn.microsoft.com/it-it/library/system.security.cryptography.ciphermode(v=vs.110).aspx о ЕЦБ:

Важно: этот режим не рекомендуется, так как он открывает двери для множества эксплойтов безопасности. Если открытый текст, подлежащий шифрованию, содержит значительное количество повторений, зашифрованный текст может быть взломан по одному блоку за раз. Также можно использовать блочный анализ для определения ключа шифрования. Также активный противник может подменять и обменивать отдельные блоки без обнаружения, что позволяет сохранять блоки и вставлять их в поток в других точках без обнаружения.

Вот некоторые результаты после enc. и уб.:

��u��T�be encrypted
U����ŋbe encrypted
5�AL\"0be encrypted

И так далее, спасибо за совет.


person DarioDF    schedule 09.04.2015    source источник
comment
Это из-за IV. Извините, пора спать, вы найдете примеры, теперь вы знаете, что искать.   -  person Maarten Bodewes    schedule 10.04.2015


Ответы (1)


Вы создали новый экземпляр TripleDESCryptoServiceProvider, но этот новый экземпляр не имеет того же значения IV, что и первый.

Также некорректно сравнивать длину зашифрованного массива с длиной расшифрованного. Вы должны попытаться вернуть исходную строку и проверить, равны ли они

private const string KEY = "Chiave";
static void Main(string[] args)
{
    string plainText = "Data to be encrypted";

    byte[] keyArray;
    MD5CryptoServiceProvider hashmd5 = new MD5CryptoServiceProvider();
    keyArray = hashmd5.ComputeHash(UTF8Encoding.UTF8.GetBytes(KEY));

    byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(plainText);

    TripleDESCryptoServiceProvider tdes = new TripleDESCryptoServiceProvider();
    tdes.Key = keyArray;
    tdes.Mode = CipherMode.CBC;
    tdes.Padding = PaddingMode.PKCS7;

    ICryptoTransform cTransform = tdes.CreateEncryptor();
    byte[] encArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);

    // REMOVE THESE LINES 
    // tdes = new TripleDESCryptoServiceProvider();
    // tdes.Key = keyArray;
    // tdes.Mode = CipherMode.CBC;
    // tdes.Padding = PaddingMode.PKCS7;

    cTransform = tdes.CreateDecryptor();
    byte[] decArray = cTransform.TransformFinalBlock(encArray, 0, encArray.Length);

    // if (encArray.Length == decArray.Length)
    // {
    //    for (int i = 0; i < encArray.Length; ++i)
    //        Console.Out.Write("{0,3}|{1,3}", encArray[i], decArray[i]);
    //} else
    //    Console.Out.Write("Length error!");

    string result = UTF8Encoding.UTF8.GetString(decArray);
    Console.WriteLine(result);

    Console.In.Read();
}
person Steve    schedule 09.04.2015
comment
Спасибо, это был IV (я пропустил вычисление строки результата как кодировку base64 зашифрованного текста, чтобы убедиться, что это не проблема кодирования) - person DarioDF; 10.04.2015