Заполнение является недействительным и не может быть удалено - случайным образом выбрасывается RijndaelManaged - PullRequest
0 голосов
/ 02 июля 2018

Я искал хорошее шифрование простого текстового файла в C #, наткнулся на сообщение на SO и уже давно пользуюсь им.

Я не помню оригинальный пост, из которого я получил код; но вот копия оригинального кода, слегка модифицированная для моего собственного использования:

public static class StringCipher
{
    private const int Keysize = 256;

    private const int DerivationIterations = 1000;

    public static string Encrypt(string plainText, string fileName)
    {
        try
        {
            var saltStringBytes = Generate256BitsOfRandomEntropy();
            var ivStringBytes = Generate256BitsOfRandomEntropy();
            var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
            using (var password = new Rfc2898DeriveBytes(Machine.Udid, saltStringBytes, DerivationIterations))
            {
                var keyBytes = password.GetBytes(Keysize / 8);
                using (var symmetricKey = new RijndaelManaged())
                {
                    symmetricKey.BlockSize = 256;
                    symmetricKey.Mode = CipherMode.CBC;
                    symmetricKey.Padding = PaddingMode.PKCS7;
                    using (var encryptor = symmetricKey.CreateEncryptor(keyBytes, ivStringBytes))
                    {
                        using (var memoryStream = new MemoryStream())
                        {
                            using (var cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write))
                            {
                                cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
                                cryptoStream.FlushFinalBlock();
                                var cipherTextBytes = saltStringBytes;
                                cipherTextBytes = cipherTextBytes.Concat(ivStringBytes).ToArray();
                                cipherTextBytes = cipherTextBytes.Concat(memoryStream.ToArray()).ToArray();
                                memoryStream.Close();
                                cryptoStream.Close();
                                return Convert.ToBase64String(cipherTextBytes);
                            }
                        }
                    }
                }
            }
        }
        catch (Exception exception)
        {
            throw new Exception("Failed to encrypt " + fileName + " - " + exception.Message, exception);
        }
    }

    public static string Decrypt(string cipherText, string fileName)
    {
        try
        {
            var cipherTextBytesWithSaltAndIv = Convert.FromBase64String(cipherText);
            var saltStringBytes = cipherTextBytesWithSaltAndIv.Take(Keysize / 8).ToArray();
            var ivStringBytes = cipherTextBytesWithSaltAndIv.Skip(Keysize / 8).Take(Keysize / 8).ToArray();
            var cipherTextBytes = cipherTextBytesWithSaltAndIv.Skip((Keysize / 8) * 2).Take(cipherTextBytesWithSaltAndIv.Length - ((Keysize / 8) * 2)).ToArray();
            using (var password = new Rfc2898DeriveBytes(Machine.Udid, saltStringBytes, DerivationIterations))
            {
                var keyBytes = password.GetBytes(Keysize / 8);
                using (var symmetricKey = new RijndaelManaged())
                {
                    symmetricKey.BlockSize = 256;
                    symmetricKey.Mode = CipherMode.CBC;
                    symmetricKey.Padding = PaddingMode.PKCS7;
                    using (var decryptor = symmetricKey.CreateDecryptor(keyBytes, ivStringBytes))
                    {
                        using (var memoryStream = new MemoryStream(cipherTextBytes))
                        {
                            using (var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read))
                            {
                                var plainTextBytes = new byte[cipherTextBytes.Length];
                                var decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
                                memoryStream.Close();
                                cryptoStream.Close();
                                return Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
                            }
                        }
                    }
                }
            }
        }
        catch (Exception exception)
        {
            throw new Exception("Failed to decrypt " + fileName + " - " + exception.Message, exception);
        }
    }

    private static byte[] Generate256BitsOfRandomEntropy()
    {
        var randomBytes = new byte[32];
        using (var rngCsp = new RNGCryptoServiceProvider())
        {
            rngCsp.GetBytes(randomBytes);
        }
        return randomBytes;
    }
}

Время от времени мое приложение случайным образом выдает это исключение:

Заполнение недействительно и не может быть удалено.

А это мой след стека:

at System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast)
   at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)
   at System.Security.Cryptography.CryptoStream.FlushFinalBlock()
   at System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing)
   at System.IO.Stream.Close()
   at System.IO.Stream.Dispose()
   at DisplayMapper.Lib.StringCipher.Decrypt(String cipherText, String fileName) in C:\Users\Latheesan\Desktop\MyApp\StringCipher.cs:line 82

Строка 82 ссылается на это:

вернуть Encoding.UTF8.GetString (plainTextBytes, 0, decryptedByteCount);

Я читал об этой ошибке, и многие посты утверждают, что тот же ключ / пароль, который использовался для шифрования, должен использоваться для расшифровки и т. Д. *

Это то, что я делаю в своей реализации, я использую статический пароль, сгенерированный из хэша серийных номеров cpu / motherboard / hdd с некоторыми случайными строками (который получается из Machine.Udid.

Итак, я не уверен, что является причиной этой ошибки. Я не был в состоянии воспроизвести это, поскольку ошибка происходит случайно. Есть идеи?

...