CryptoStream выдает ошибку при закрытии при расшифровке - PullRequest
1 голос
/ 11 июля 2019

Я пытаюсь зашифровать простой текст с помощью класса RijndaelManaged, а затем расшифровать зашифрованную строку, чтобы в конце получился такой же простой текст.*

    protected static string AESEncrypt(string plainText, string key)
    {
        byte[] encryptedBytes = null;

        byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

        using (MemoryStream ms = new MemoryStream())
        {
            using (RijndaelManaged aes = new RijndaelManaged())
            {
                aes.KeySize = 256;
                aes.BlockSize = 128;

                var keyHold = new Rfc2898DeriveBytes(key, saltBytes, 1000);

                aes.Key = keyHold.GetBytes(aes.KeySize / 8);
                aes.IV = keyHold.GetBytes(aes.BlockSize / 8);

                aes.Mode = CipherMode.CBC;

                var bytesToBeEncrypted = Encoding.UTF8.GetBytes(plainText);

                using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
                    cs.Close();
                }

                encryptedBytes = ms.ToArray();
            }
        }

        return Convert.ToBase64String(encryptedBytes);
    }

Например, я шифрую этот простой текст "encryptMe", вызывая вышеупомянутую функцию как var encryptedString = AESEncrypt(plainText, "lockMe");.В результате получается nKytZ86r0DDKSzD3ph+ntg==.

Затем я отправляю эту зашифрованную строку нижеприведенной функции:

    protected static string AESDecrypt(string cryptedText, string key)
    {
        byte[] decryptedBytes = null;

        byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };

        using (MemoryStream ms = new MemoryStream())
        {
            using (RijndaelManaged aes = new RijndaelManaged())
            {
                aes.KeySize = 256;
                aes.BlockSize = 128;

                var keyHold = new Rfc2898DeriveBytes(key, saltBytes, 1000);

                aes.Key = keyHold.GetBytes(aes.KeySize / 8);
                aes.IV = keyHold.GetBytes(aes.BlockSize / 8);

                aes.Mode = CipherMode.CBC;

                var bytesToBeDDecrypted = Encoding.UTF8.GetBytes(cryptedText);

                using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(bytesToBeDDecrypted, 0, bytesToBeDDecrypted.Length);
                    cs.Close();
                }

                decryptedBytes = ms.ToArray();
            }
        }

        return Encoding.UTF8.GetString(decryptedBytes);
    }

В этом методе код выдает ошибку The input data is not a complete block, оставляя CryptoStream.

Мои KeySize и BlockSize делятся на 8, и я не вижу, что я пропускаю.

1 Ответ

3 голосов
/ 11 июля 2019

В AESDecrypt у вас есть:

var bytesToBeDDecrypted = Encoding.UTF8.GetBytes(cryptedText);

Поскольку вы передаете шифр с кодировкой base-64, вместо этого должно быть

var bytesToBeDDecrypted = Convert.FromBase64String(cryptedText);

Есть также некоторые улучшения безопасности, которые вы должны сделать. Вы должны увеличить количество итераций с 1000 до чего-то намного большего, по крайней мере, до 65K. Соль должна быть не менее 12 байтов и должна генерироваться случайным образом для каждого шифрования. Его не нужно хранить в секрете, обычно удобно добавлять его к шифру. Затем расшифровщик извлекает соль из переданного зашифрованного текста. Вам также следует использовать код аутентификации сообщений (MAC), чтобы предотвратить подделку. Обратите внимание, что режим AES-GCM, а также некоторые другие режимы включают этот MAC в качестве неотъемлемой части их работы. Однако, если AES-GCM недоступен, то HMAC-SHA256, вероятно, будет и является приемлемым.

...