Bad PKCS7 padding. Invalid length 0. Python Encryption to C# Decryption
我正在尝试在 Xamarin/.Net/C# prgram 和使用 AES CBC 的 python 程序之间共享数据。我能够在 .Net 中加密消息并在 python 中成功解密该消息,但反之亦然。也就是说,当我首先在 python 中加密并尝试在 C# 中解密该消息时,出现异常:”Bad PKCS7 padding. Invalid length 0″
这是我在 Python 中使用的 Python 加密:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
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#中的解密:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
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#中加密相同的字符串要短得多。谢谢你的帮助。
1 2
|
length = 16 – (len(textToEncrypt) % 16)
textToEncrypt += length * b‘//0′
|
这不是 PKCS7 填充的工作原理。
关于填充的问题是您需要一种方法来识别它,以便以后可以将其删除,而不会意外留下一些或删除一些认为它是填充的数据。
PKCS7 通过使用其值是填充字节数的字节填充来做到这一点。所以填充将是
之一
1 2 3 4 5 6
|
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 字节)的精确倍数,并且您选择根本不添加任何填充,那么当您删除填充时,您可能会发现您的数据自然以 或 02 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 必须是随机不可预测的(它可以是公开的,但不能与您之前加密的内容相同)。随机生成它然后将其添加到密文的开头是很常见的。不要从您的密钥中派生它。
- 对于 CBC,IV 不仅需要随机,还应该是不可预测的。
-
@kelalaka 是否有任何可预测的随机(非伪随机)数字序列?如果一个 RNG 产生可预测的值,它肯定不够随机吗?我没有密码学背景,但直观地说,可预测数字集是随机数字集的超集,而不是相反(即,你可以在没有随机性的情况下获得不可预测性,但反过来不行)?
-
Rfc2898DeriveBytes 使用伪随机函数。重点是 Dual_EC_DRBG。
-
@kelalaka 我认为这不能解决我的问题?我不提倡将 Rfc2898DeriveBytes 用于 IV
-
CSPRNG 我们更喜欢用好种子。你不提倡,也不给。真正的随机性很难实现。硬件随机数生成器通常很慢并且可能需要特殊介质,这通常用作 CSPRNG 的种子。是否有任何可预测的真正随机(非伪随机)数字序列?我不知道。例如,可能你更了解,python os.urandom
-
很好读 TRNG 和 CSPRNG 有什么区别?什么时候 RNG 是 CSPRNG、CSRNG 或 TRNG?
-
回到我的观点,你说”IV 需要不仅仅是随机的,它应该是可预测的”。我的问题是,随机性不是比可预测性更严格的要求吗?也就是说,不是所有的随机序列都是不可预测的,而且不是所有的不可预测的序列都是随机的吗?
-
第一段随机性。你能定义你的随机性吗?
-
让我们在聊天中继续这个讨论。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/267966.html