RijndaelManaged, для определенного ввода могут быть расшифрованы оба набора разных ключей

Методы шифрования и дешифрования предоставлены Microsoft документация.

У меня есть два разных набора ключей. Когда я использую key1 для шифрования и key2 для дешифрования, я ожидаю, что будет выброшено CryptographicException, но на самом деле это искаженный текст.

class Program
{
    private static readonly byte[] key1 = new byte[] { 0xAC, 0x1F, 0xC4, 0x8F, 0x4C, 0x79, 0x10, 0xA1, 0x11, 0xD6, 0x7D, 0x24, 0xCE, 0x73, 0x6C, 0xE7, 0x8E, 0xD2, 0x97, 0xC2, 0x90, 0x21, 0x27, 0xE9, 0x68, 0x3F, 0x50, 0x5B, 0x92, 0x40, 0x6D, 0xC9 };
    private static readonly byte[] iv1 = new byte[] { 0xF8, 0x14, 0x77, 0xFE, 0xFC, 0x84, 0x8E, 0x66, 0x82, 0x58, 0x01, 0x6D, 0x43, 0x12, 0xD8, 0x6F };

    private static readonly byte[] key2 = new byte[] { 0x9D, 0xD8, 0x77, 0x5D, 0xA4, 0x60, 0x14, 0xFE, 0x89, 0xB6, 0xAF, 0x40, 0x2B, 0xFE, 0xE5, 0xD2, 0x0B, 0xDF, 0x55, 0x26, 0x37, 0x77, 0x6F, 0x21, 0x9A, 0x27, 0xB4, 0xD7, 0x08, 0xEA, 0xC6, 0xB9 };
    private static readonly byte[] iv2 = new byte[] { 0x4D, 0x24, 0x83, 0x94, 0x3D, 0x29, 0x86, 0x7F, 0x40, 0x3A, 0x4F, 0x87, 0x37, 0x0B, 0x11, 0x8E };

    static void Main(string[] args)
    {
        var ticks = 637375909118731913;
        string original = JsonConvert.SerializeObject(new DateTime(ticks, DateTimeKind.Utc));

        using (RijndaelManaged myRijndael = new RijndaelManaged())
        {
            byte[] encrypted = EncryptStringToBytes(original, key1, iv1);
            Console.WriteLine("Original:   {0}", original);

            string roundtrip = DecryptStringFromBytes(encrypted, key1, iv1);
            Console.WriteLine("Round Trip: {0}", roundtrip);

            try
            {
                string roundtrip2 = DecryptStringFromBytes(encrypted, key2, iv2);
                Console.WriteLine("Round Trip2: {0}", roundtrip2);
            }
            catch (CryptographicException e)
            {
                Console.WriteLine("Round Trip2: Unable to decrypt, expected.");
            }
        }
    }

    static byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
    {
        byte[] encrypted;

        using (RijndaelManaged rijAlg = new RijndaelManaged())
        {
            rijAlg.Key = Key;
            rijAlg.IV = IV;

            ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);

            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {

                        swEncrypt.Write(plainText);
                    }
                    encrypted = msEncrypt.ToArray();
                }
            }
        }

        return encrypted;
    }

    static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
    {
        string plaintext = null;

        using (RijndaelManaged rijAlg = new RijndaelManaged())
        {
            rijAlg.Key = Key;
            rijAlg.IV = IV;

            ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);

            using (MemoryStream msDecrypt = new MemoryStream(cipherText))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {
                        plaintext = srDecrypt.ReadToEnd();
                    }
                }
            }
        }

        return plaintext;
    }
}

Вывод:

Original:   "2020-10-06T14:21:51.8731913Z"
Round Trip: "2020-10-06T14:21:51.8731913Z"
Round Trip2: 7cB?]?wV???DFI?|hgY?Q?&x

Ожидайте:

Original:   "2020-10-06T14:21:51.8731913Z"
Round Trip: "2020-10-06T14:21:51.8731913Z"
Round Trip2: Unable to decrypt, expected.

Это происходит только в конкретном вводе, если я изменяю значение тиков

var ticks = 637375909118731914;

Все работает как положено.

Какую ошибку я сделал?

Примечание.

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


person Libron    schedule 06.10.2020    source источник
comment
Конкретное криптографическое исключение, с которым вы (имеете дело / ищете), связано с плохим заполнением. К сожалению, проверка заполнения - это очень слабая проверка целостности - многие неверные ключи проходят проверку заполнения и создают мусор.   -  person Damien_The_Unbeliever    schedule 06.10.2020
comment
Я нашел какой-то пример, он просто перехватывает все исключения, но, похоже, это не решает мою проблему. Есть ли способ определить, успешно ли расшифровка?   -  person Libron    schedule 06.10.2020
comment
@LiTang Вы можете добавить текст перед сообщением, который вы можете проверить после расшифровки   -  person 404    schedule 06.10.2020
comment
RijndaelManaged, похоже, не имеет существующего метода для проверки результатов, кажется, мне нужно написать дополнительный код для решения этой проблемы.   -  person Libron    schedule 06.10.2020


Ответы (1)


Мое решение - определить, находится ли строка в формате json.

if(IsJson(roundtrip))
{
   Console.WriteLine("Round Trip: {0}", roundtrip);
}
else
{
   Console.WriteLine("Round Trip: Unable to decrypt.");
}
person Libron    schedule 06.11.2020