该代码中如何解决“要解密的数据长度无效”的问题

时间:2019-02-04 14:00:15

标签: c# encryption

我在下面的代码上遇到了一些麻烦。 不是我自己的,我是从this question on Stack Overflow复制过来的。

public readonly byte[] salt = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Must be at least eight bytes.  MAKE THIS SALTIER!
public const int iterations = 1042; // Recommendation is >= 1000.       


/// <summary>Decrypt a file.</summary>
/// <remarks>NB: "Padding is invalid and cannot be removed." is the Universal CryptoServices error.  Make sure the password, salt and iterations are correct before getting nervous.</remarks>
/// <param name="sourceFilename">The full path and name of the file to be decrypted.</param>
/// <param name="destinationFilename">The full path and name of the file to be output.</param>
/// <param name="password">The password for the decryption.</param>
/// <param name="salt">The salt to be applied to the password.</param>
/// <param name="iterations">The number of iterations Rfc2898DeriveBytes should use before generating the key and initialization vector for the decryption.</param>
public void DecryptFile(string sourceFilename, string destinationFilename, string password, byte[] salt, int iterations)
{
    AesManaged aes = new AesManaged();
    aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
    aes.KeySize = aes.LegalKeySizes[0].MaxSize;
    // NB: Rfc2898DeriveBytes initialization and subsequent calls to   GetBytes   must be eactly the same, including order, on both the encryption and decryption sides.
    Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt, iterations);
    aes.Key = key.GetBytes(aes.KeySize / 8);
    aes.IV = key.GetBytes(aes.BlockSize / 8);
    aes.Mode = CipherMode.CBC;
    ICryptoTransform transform = aes.CreateDecryptor(aes.Key, aes.IV);

    using (FileStream destination = new FileStream(destinationFilename, FileMode.CreateNew, FileAccess.Write, FileShare.None))
    {
        using (CryptoStream cryptoStream = new CryptoStream(destination, transform, CryptoStreamMode.Write))
        {
            try
            {
                using (FileStream source = new FileStream(sourceFilename, FileMode.Open, FileAccess.Read, FileShare.Read))
                {
                    source.CopyTo(cryptoStream);
                    source.Flush();
                }
            }
            catch (CryptographicException exception)
            {
                if (exception.Message == "Padding is invalid and cannot be removed.")
                    throw new ApplicationException("Universal Microsoft Cryptographic Exception (Not to be believed!)", exception);
                else
                    throw;
            }
        }
    }
}

/// <summary>Encrypt a file.</summary>
/// <param name="sourceFilename">The full path and name of the file to be encrypted.</param>
/// <param name="destinationFilename">The full path and name of the file to be output.</param>
/// <param name="password">The password for the encryption.</param>
/// <param name="salt">The salt to be applied to the password.</param>
/// <param name="iterations">The number of iterations Rfc2898DeriveBytes should use before generating the key and initialization vector for the decryption.</param>
public void EncryptFile(string sourceFilename, string destinationFilename, string password, byte[] salt, int iterations)
{
    AesManaged aes = new AesManaged();
    aes.BlockSize = aes.LegalBlockSizes[0].MaxSize;
    aes.KeySize = aes.LegalKeySizes[0].MaxSize;
    // NB: Rfc2898DeriveBytes initialization and subsequent calls to   GetBytes   must be eactly the same, including order, on both the encryption and decryption sides.
    Rfc2898DeriveBytes key = new Rfc2898DeriveBytes(password, salt, iterations);
    aes.Key = key.GetBytes(aes.KeySize / 8);
    aes.IV = key.GetBytes(aes.BlockSize / 8);
    aes.Mode = CipherMode.CBC;
    ICryptoTransform transform = aes.CreateEncryptor(aes.Key, aes.IV);

    using (FileStream destination = new FileStream(destinationFilename, FileMode.CreateNew, FileAccess.Write, FileShare.None))
    {
        using (CryptoStream cryptoStream = new CryptoStream(destination, transform, CryptoStreamMode.Write))
        {
            using (FileStream source = new FileStream(sourceFilename, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                source.CopyTo(cryptoStream);
            }
        }
    }
}

此后,我得到一个例外:要解密的数据长度无效。 但是,无论如何,我加密的那个文件都会被加密,但是当您尝试解密该文件时,它会显示以下消息:没有足够的内存来完成此操作。 无论如何,它可以正确地用于多媒体文件(我尝试过.mp3,.mkv,.jpg),但是不适用于文档(.txt,.docx)。因此,我希望有人可以帮助我解决这个问题,还有另一个问题(针对该主题)。如何为每个文件保存密码?每次,当您使用错误的密码解密文件时,它都不会解密该文件。有没有办法显示密码不正确?

0 个答案:

没有答案