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

问题描述 投票:0回答:1

我正在尝试使用AES CBC在Xamarin / .Net / C#prgram和python程序之间共享数据。我能够在.Net中加密消息,并在python中成功解密该消息,反之则不然。也就是说,当我首先在python中加密并尝试在C#中解密该消息时,出现异常:“错误的PKCS7填充。无效的长度0”

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

salt = 16 * b'\0'
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'\0'
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#中加密相同的字符串要短得多。谢谢你的帮助。

c# python cryptography aes pycrypto
1个回答
0
投票
length = 16 - (len(textToEncrypt) % 16)
textToEncrypt += length * b'\0'

这不是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字节),并且您选择根本不添加任何填充,那么当您删除填充时,您可能会发现数据自然以[C0 ]或01等,您会删除那些认为它们已填充的有效数据字节。因此,在这种情况下,您需要添加完整的填充块。

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


python中的加密字符串比在C#中加密相同的字符串要短得多。谢谢你的帮助。

我认为您可能会混淆编码。 00是UTF16-LE,每个字符使用2个字节。在Python中使用它是非常不寻常的:您更可能使用的是UTF-8之类的字符,对于常见的西方字符,每个字符使用1个字节。在不知道如何将Python字符串转换为字节字符串的情况下很难确定地说。


[使用AES,IV必须是随机的(可以是公开的,但不能与您加密的先前内容相同)。通常随机生成它,然后将其添加到密文的开头。不要从您的密钥派生它。

© www.soinside.com 2019 - 2024. All rights reserved.