【问题标题】:c# AES decryption errors with "Padding is invalid and cannot be removed."c# AES 解密错误,显示“填充无效且无法删除。”
【发布时间】:2018-01-02 17:18:59
【问题描述】:

我正在尝试编写客户端软件,该软件使用 c# 对设备执行 AES 加密和解密消息。

使用 System.Security.Cryptography 中的 AES 类,向设备发送加密消息没有问题。设备成功解密。

解密从设备收到的消息时会出现此问题。我们收到消息:“填充无效,无法删除。”

我在网上搜索并尝试了三种不同的方法,但都有相同的错误 - 见下文。在没有设置 KeySize 属性的情况下,我也尝试了这三种方法。

除了用 C# 编写的客户端之外,还编写了一个 python 客户端,其中一切正常 - 使用 python aes 库。 因此,有了一个 python 版本,我能够比较接收到的 cipherText 的长度,该长度为 32 个字节,是一个字节数组。 15 个字节是填充。 非常感谢帮助。

Option 1
byte[] messageBuffer = null;
using (Aes aesAlg = Aes.Create())
{
    aesAlg.BlockSize = 128;
    aesAlg.KeySize = 128;
    aesAlg.Mode = CipherMode.CBC;
    aesAlg.Key = encryptionKey;  //used by device to encrypt. encryptionKey is a 16 byte array
    aesAlg.IV = sentIV; //This agrees with the IV that was used to encrypt the message by the device. sentIV is a 16 byte array
    //aesAlg.Padding = PaddingMode.PKCS7;  // this makes no difference

    byte[] cipherText = encryptedMessagePart;   //encryptedMessagePart is byte[] encryptedMessagePart

    // Create a decrytor to perform the stream transform. 
    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

    try
    {
        messageBuffer = decryptor.TransformFinalBlock(cipherText, 0, cipherText.Length);  //****fails here ********************
    }

    catch (Exception ex)
    {
        ....;
    }
}



Option 2
byte[] messageBuffer = new byte [1024];
using (Aes aesAlg = Aes.Create())
{
    aesAlg.BlockSize = 128;
    aesAlg.KeySize = 128;
    aesAlg.Mode = CipherMode.CBC;
    aesAlg.Key = encryptionKey;  //used by device to encrypt. encryptionKey is a 16 byte array
    aesAlg.IV = sentIV; //This agrees with the IV that was used to encrypt the message by the device. sentIV is a 16 byte array
    //aesAlg.Padding = PaddingMode.PKCS7;  // this makes no difference

    byte[] cipherText = encryptedMessagePart; //encryptedMessagePart is byte[] encryptedMessagePart

    // Create a decrytor to perform the stream transform. 
    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
    using (var msDecrypt = new MemoryStream(cipherText))
    {
        using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
        {
            try
            {
                var zx = csDecrypt.Read(messageBuffer, 0, cipherText.Length); //****fails here ********************
            }
            catch (Exception ex)
            {
                ....;
            }
       }
    }
}


Option 3
byte[] messageBuffer = new byte [1024];
using (Aes aesAlg = Aes.Create())
{
    aesAlg.BlockSize = 128;
    aesAlg.KeySize = 128;
    aesAlg.Mode = CipherMode.CBC;
    aesAlg.Key = encryptionKey;  //used by device to encrypt. encryptionKey is a 16 byte array
    aesAlg.IV = sentIV; //This agrees with the IV that was used to encrypt the message by the device. sentIV is a 16 byte array
    //aesAlg.Padding = PaddingMode.PKCS7;  // this makes no difference

    byte[] cipherText = encryptedMessagePart; //encryptedMessagePart is byte[] encryptedMessagePart

    // Create a decrytor to perform the stream transform. 
    ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
    using (var msDecrypt = new MemoryStream(cipherText))
    {
        using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
        {
        using (var srDecrypt = new StreamReader(csDecrypt))
            {
                try
                {
                    // Read the decrypted bytes from the decrypting stream 
                    // and place them in a string. 
                    var pt = srDecrypt.ReadToEnd(); //****fails here ********************
                    messageBuffer = Utils.GetBytes(pt); //convert to bytes
                }
                catch (Exception ex)
                {
                    ....;
                }
            }
        }
    }
}

【问题讨论】:

  • 那么,你的设备到底使用了什么填充模式?
  • 该错误通常与填充有关,但意味着由于某种原因解密失败
  • @Plutonix 不一定;请参阅下面的答案。

标签: c# encryption cryptography aes


【解决方案1】:

密钥或消息已损坏的任何内容都会出现填充错误。对于小于一个块的小消息,也可能是 IV 处理不正确。由于设备似乎在使用 C#,这是最可能的原因。

使用ISO 10126 padding 的可能性要小得多,但也有可能。可以使用 ISO 10126 取消填充例程取消填充 PKCS#7 填充消息。但是,相反的情况并非如此,因为 PKCS#7 依赖于填充中的所有值都是正确的,而不仅仅是最后一个。在 ISO 10126 填充中,只有最后一个字节表示使用的填充字节数;其他字节可以有任何值。

您当然可以随时查看。只需指示“无填充”并以十六进制打印出消息。如果消息完全是垃圾,则消息甚至更有可能密钥不正确。如果看起来没问题,那么您应该能够将填充方法与最后一个字节区分开来;维基百科关于填充的文章列出了所有常见的方案。

【讨论】:

    【解决方案2】:

    我通过在解密例程中非常简单地解决了这个问题,通过以下方式将填充模式显式设置为无:

    aesAlg.Padding = PaddingMode.None;
    

    在最初的python例程中,没有使用填充模式。 我错误地认为,通过不说明填充模式,填充模式将是无。 (如果您想知道,加密例程仅用 python 编写。解密例程是用 Python 和 C# 编写的)

    【讨论】:

      猜你喜欢
      • 2016-02-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-15
      • 2016-07-18
      • 2018-07-17
      • 1970-01-01
      相关资源
      最近更新 更多