Rijndael填充或长度无效 [英] Rijndael padding or length is invalid

查看:322
本文介绍了Rijndael填充或长度无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Rijndael或Aes和下面的代码对字符串进行加密/解密。

I am trying to encrypt/decrypt a string using eith Rijndael or Aes and the code below.

public class Crypto
{
    private const string defaultVector = "asdfg123456789";
    private const CipherMode cipherMode = CipherMode.CBC;
    //Have tried PaddingMode.ISO10126, PaddingMode.None, and PaddingMode.PKCS7
    private const PaddingMode paddingMode = PaddingMode.ISO10126;
    private const int iterations = 2;
    private static Rijndael GetCrypto(string passphrase)
    {
        var crypt = Rijndael.Create();
        crypt.Mode = cipherMode;
        crypt.Padding = paddingMode;
        crypt.BlockSize = 256;
        crypt.KeySize = 256;
        crypt.Key =
            new Rfc2898DeriveBytes(passphrase, Encoding.Unicode.GetBytes(defaultVector), iterations).GetBytes(32);
        crypt.IV = new Rfc2898DeriveBytes(passphrase, Encoding.Unicode.GetBytes(defaultVector), iterations).GetBytes(32);
        return crypt;
    }
    public static string Encrypt(string plainText, string passphrase)
    {
        byte[] clearData = Encoding.Unicode.GetBytes(plainText);
        byte[] encryptedData;
        var crypt = GetCrypto(passphrase);
        using (var ms = new MemoryStream())
        {
            using (var cs = new CryptoStream(ms, crypt.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cs.Write(clearData, 0, clearData.Length);
                //cs.FlushFinalBlock(); //Have tried this active and commented with no change.
            }
            encryptedData = ms.ToArray();
        }
        //Changed per Xint0's answer.
        return Convert.ToBase64String(encryptedData);
    }
    public static string Decrypt(string cipherText, string passphrase)
    {
        //Changed per Xint0's answer.
        byte[] encryptedData = Convert.FromBase64String(cipherText);
        byte[] clearData;
        var crypt = GetCrypto(passphrase);
        using (var ms = new MemoryStream())
        {
                using (var cs = new CryptoStream(ms, crypt.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    cs.Write(encryptedData, 0, encryptedData.Length);
                    //I have tried adding a cs.FlushFinalBlock(); here as well.
                }
                clearData = ms.ToArray();
        }
        return Encoding.Unicode.GetString(clearData);
    }
}

//编辑:我已经对Unicode调用进行了更改根据下面的Xint0的答案转换为Convert.ToBase64String。

//Edits: I have changed over the Unicode calls to Convert.ToBase64String per Xint0's answer below.

在cs.Write in Decrypt方法上,我收到以下错误:填充无效,无法删除。

On the cs.Write in Decrypt method, I am getting the error that "Padding is invalid and cannot be removed."

我尝试将填充设置为PaddingMode.None,但得到要加密的数据长度无效。

I have tried setting the padding to PaddingMode.None but I get "Length of the data to encrypt is invalid." on the cs.Write in the Encrypt method.

我已经看过这些了,但是他们说的什么似乎都不起作用。

I've looked at these and nothing they've said seems to work.

填充无效且无法删除

填充无效且

堆栈跟踪显示System.Security.CryptographicException来自RijndaelManagedTransform.DecryptData(Byte [] inputBuffer,Int32 inputOffset,Int32 inputCount,Byte []& outputBuffer,Int32 outputOffset,PaddingMode paddingMode,布尔值fLast)。

Stack trace shows System.Security.CryptographicException is coming from RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast).

推荐答案

我看到两个问题:


  1. 在调用 ms.ToArray()之前,您并没有刷新和关闭流。更改为:

  1. You are not flushing and closing the streams before calling ms.ToArray(). Change it to:

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

ms.Close();
encryptedData = ms.ToArray();
...


  • 加密得到的字节数组 encryptedData 一个Unicode字符串,但是您正在使用Unicode编码器从字节数组中获取字符串。而不是使用 Encrypt System.Convert中的 System.Convert.ToBase64String()解密中的FromBase64String()

  • In Encrypt the resulting byte array encryptedData is NOT a Unicode string, yet you are using a Unicode encoder to get a string from the byte array. Instead of that use System.Convert.ToBase64String() in Encrypt and System.Convert.FromBase64String() in Decrypt.

    加密中执行

    return System.Convert.ToBase64String(encryptedData);
    

    解密中执行:

    byte[] encryptedData = System.Convert.FromBase64String(cipherText);
    

    编辑

    最大的问题是 Encrypt 的返回值。加密Unicode字符串的字节表示形式的结果是 NOT 的Unicode字符串的字节表示形式。您不应将 encryptedData 的值与 Encoding.Unicode.GetString()一起使用,以获取加密后的字符串表示形式数据。使用 System.Convert.ToBase64String()获取加密数据的字符串表示形式。请参阅编码类 MSDN文档中的备注部分。

    The biggest problem is the return value of Encrypt. The result of encrypting the byte representation of a Unicode string is NOT a byte representation of a Unicode string. You should not use the value of encryptedData with Encoding.Unicode.GetString() to get a string representation of the encrypted data. Use System.Convert.ToBase64String() to get a string representation of the encrypted data. Please see the Remarks section in the Encoding Class MSDN Documentation.

    编辑2

    请注意,如果您要与AES互操作,Rijndael并非完全是AES块大小应始终为128位,与密钥大小无关。有关详细信息,您可以阅读此处

    Note that Rijndael is not exactly AES, if you are interoperating with AES the block size should always be 128-bits, independent of the key size. For details you can read about it here.

    这篇关于Rijndael填充或长度无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆