【问题标题】:Rijndael encrypted text causes length of data to decrypt is invalid error - C#Rijndael 加密文本导致要解密的数据长度无效错误 - C#
【发布时间】:2015-05-19 18:22:45
【问题描述】:

我在网上搜索过,但没有找到任何解决我的问题的方法。

我正在使用以前编写的方法使用 Rijndael 类对文本进行加密和加密。

我使用这些函数来加密和解密我一直在开发的 Web 应用程序的用户名和电子邮件。

加密/解密工作完美,但每隔一段时间我就会收到此错误:

System.Security.Cryptography.CryptographicException: Length of the data to decrypt is invalid.

目前,我使用特定的电子邮件地址收到此错误,即使我替换了电子邮件中的某些字母,我也无法重现该错误。

这里是加密/解密函数。 IV 和 Key 被定义为只读字符串。

    static public string Encrypting(string Source)
{
    byte[] bytIn = System.Text.ASCIIEncoding.ASCII.GetBytes(Source);
    // create a MemoryStream so that the process can be done without I/O files
    System.IO.MemoryStream ms = new System.IO.MemoryStream();

    byte[] IVBytes = Encoding.ASCII.GetBytes(IV);
    byte[] KEYBytes = Encoding.ASCII.GetBytes(KEY);

    Rijndael rijndael = Rijndael.Create();
    rijndael.IV = IVBytes;
    rijndael.Key = KEYBytes;

    // create Crypto Stream that transforms a stream using the encryption
    CryptoStream cs = new CryptoStream(ms, rijndael.CreateEncryptor(), CryptoStreamMode.Write);

    // write out encrypted content into MemoryStream
    cs.Write(bytIn, 0, bytIn.Length);
    cs.FlushFinalBlock();

    // get the output and trim the '\0' bytes
    byte[] bytOut = ms.GetBuffer();
    int i = 0;
    for (i = 0; i < bytOut.Length; i++)
        if (bytOut[i] == 0)
            break;

    // convert into Base64 so that the result can be used in xml
    return System.Convert.ToBase64String(bytOut, 0, i);
}

static public string Decrypting(string Source)
{
    // convert from Base64 to binary
    byte[] bytIn = System.Convert.FromBase64String(Source);
    // create a MemoryStream with the input
    System.IO.MemoryStream ms = new System.IO.MemoryStream(bytIn, 0, bytIn.Length);

    byte[] IVBytes = Encoding.ASCII.GetBytes(IV);
    byte[] KEYBytes = Encoding.ASCII.GetBytes(KEY);

    Rijndael rijndael = Rijndael.Create();
    rijndael.IV = IVBytes;
    rijndael.Key = KEYBytes;

    // create Crypto Stream that transforms a stream using the decryption
    CryptoStream cs = new CryptoStream(ms, rijndael.CreateDecryptor(), CryptoStreamMode.Read);

    // read out the result from the Crypto Stream
    System.IO.StreamReader sr = new System.IO.StreamReader(cs);
    return sr.ReadToEnd();
}

仅供参考 - 我对密码学和安全性非常陌生。

是否可以修复这些函数以避免导致错误的特殊情况,或者我应该废弃这些函数并使用RijndaelManaged 类?

我发现使用 RijndaelManaged 的​​网站: SeeSharp

TekEye

【问题讨论】:

  • pastebin.com/BNHLU1Tc 试试这个并说是否会发生同样的错误。我看到的问题与要解密的数据的无效填充有关。或者解密数据填充的设置无效,因此该方法无法计算正确的无填充的纯加密字节大小。
  • 您是否已验证您尝试解密的值是否使用相同的文本编码进行了加密?
  • @Kosmos - 谢谢,我会解决这个问题的。
  • @CamBruce - 是的,我确定。所有代码都在上面,并确保我有一个可以加密和解密文本的文本应用程序。问题在于算法以及某些字符串如何导致它抛出该错误。

标签: c# exception encryption cryptography


【解决方案1】:

这个问题几乎肯定与Rijndael 与RijndaelManaged(或任何其他此类实现)无关,而是因为加密数据包含0x00,并且您错误地假设密文结束在第一个 0x00 字节。由于密文可以合法地包含 任何 字节值,因此您应该改用流的 Length 属性来确定密文的长度。

删除您评论的部分:“获取输出并修剪 '\0' 字节”并将return ... 语句替换为:

return System.Convert.ToBase64String(ms.GetBuffer(), 0, ms.Length);

应该注意的是,您在此处使用密码学还有许多其他问题,例如使用直接从字符串的 ASCII 编码生成的密钥,以及使用固定 IV 的事实都会对安全性产生负面影响。

【讨论】:

  • 谢谢。这解决了我的问题,虽然 ms.Length 很长,但我必须使用 System.Convert.ToInt32(ms.Length) 将其转换为 int。
  • @RXC 直接转换为int 应该没问题(即(int)ms.Length),不需要更长的System.Convert...。
【解决方案2】:

错误的标准是填充问题。您使用的是哪个版本的 .NET?使用 AES 类(AES 或高级加密标准,即 Rijndael)更为常见。您可以找到大量的 AES 实现作为示例。

如果您需要证明 AES 是 Rijndael:http://en.wikipedia.org/wiki/Advanced_Encryption_Standard

【讨论】:

  • 我正在使用 .Net 3.5。感谢您的维基链接。我曾希望也许有一个简单的解决方案,但我可能会像你说的那样使用不同的实现更好。
猜你喜欢
  • 1970-01-01
  • 2010-12-22
  • 2013-04-28
  • 1970-01-01
  • 2013-07-12
  • 2010-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多