PKCS7 填充错误。无效长度 0。Python 加密到 C# 解密

Bad PKCS7 padding. Invalid length 0. Python Encryption to C# Decryption

我正在尝试使用 AES CBC 在 Xamarin/.Net/C# prgram 和 python 程序之间共享数据。我能够在 .Net 中加密消息并在 python 中成功解密该消息,但反之则不行。也就是说,当我先在 python 中加密并尝试在 C# 中解密该消息时,出现异常:"Bad PKCS7 padding. Invalid length 0"

这是我在 Python 中使用的 python 加密:

salt = 16 * b'[=11=]'
keyIV = PBKDF2(Config.SECRET, salt).read(48)
key = keyIV[:32]
iv = keyIV[-16:]
aes = AES.new(key, AES.MODE_CBC, iv)

# padding
length = 16 - (len(textToEncrypt) % 16)
print(len(textToEncrypt))
textToEncrypt += length * b'[=11=]'
print(len(textToEncrypt))

encrypted = aes.encrypt(textToEncrypt)
encoded = base64.b64encode(encrypted)
return encoded

下面是 C# 中的解密:

if (textToDecrypt == null || textToDecrypt.Length == 0)
            return "";

        textToDecrypt = textToDecrypt.Replace(" ", "+");
        byte[] bytesToDecrypt = Convert.FromBase64String(textToDecrypt);
        string decryptedText;
        using (Aes aes = Aes.Create())
        {
            byte[] salt = new byte[16];
            Rfc2898DeriveBytes crypto = new Rfc2898DeriveBytes(Config.SECRET, salt);
            aes.Padding = PaddingMode.PKCS7;
            aes.Mode = CipherMode.CBC;
            aes.Key = crypto.GetBytes(32);
            aes.IV = crypto.GetBytes(16);
            using (MemoryStream mStream = new MemoryStream())
            {
                using (CryptoStream cStream = new CryptoStream(mStream, aes.CreateDecryptor(), CryptoStreamMode.Write))
                {
                    cStream.Write(bytesToDecrypt, 0, bytesToDecrypt.Length);
                }
                decryptedText = Encoding.Unicode.GetString(mStream.ToArray());
            }
        }
        return decryptedText;

程序之间的密钥和iv匹配,但python中的加密字符串比在C#中加密相同的字符串要短得多。谢谢你的帮助。

length = 16 - (len(textToEncrypt) % 16)
textToEncrypt += length * b'[=10=]'

PKCS7 填充不是这样工作的。

关于填充的事情是你需要一种方法来识别它,这样你就可以在以后删除它,而不会不小心留下一些或删除一些认为它是填充的数据。

PKCS7 通过填充值为填充字节数的字节来做到这一点。所以填充将是

之一
01
02 02
03 03 03
04 04 04 04
...
16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16

为什么填充为 16?好吧,如果您的数据长度是块大小(16 字节)的精确倍数,并且您选择根本不添加任何填充,那么当您删除填充时,您可能会发现您的数据自然以 0102 02,等等,你会删除那些认为它们正在填充的有效数据字节。所以在这种情况下你需要添加一个完整的填充块。

您的代码的问题是它使用值 00 作为填充。


the encryption string in python comes out to be much shorter than encrypting the same string in C#. Thanks for any help.

我认为您可能混淆了编码。 Encoding.Unicode 是 UTF16-LE,每个字符使用 2 个字节。从 Python 使用它是非常不寻常的:您更有可能使用类似 UTF-8 的东西,它对常见的西方字符使用每个字符 1 个字节。在不知道如何将 Python 字符串转换为字节字符串的情况下很难确定。


使用 AES,IV 需要 随机 不可预测(可以是 public,但不能与您之前加密的内容相同)。随机生成它然后将其添加到密文的开头是很常见的。不要从您的密钥中导出它。