AES解密失败,并显示“填充无效且无法删除". [英] AES decrypt fails with "Padding is invalid and cannot be removed"

查看:388
本文介绍了AES解密失败,并显示“填充无效且无法删除".的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Java编写服务器来制作跨平台应用程序,因此最终使用Windows的C#. 最终,我克服了所有障碍,例如使用这两种语言的BigIntegers的字节序不同(Java:big endian,C#:little),因此我也成功进行了密钥交换. 现在这是问题所在了,在Java中,我使用AES/CBC/PKCS5Padding进行加密,但是在C#中没有可用的PKCS5,,但是正如我在SO上此主题的其他文章中所读到的那样,PKCS7被告知与PKCS5或那个Java实际上使用PKCS7而不是PKCS5.我不知道什么是正确的.

I am making cross-platform application with server being written in Java, so I ended up with C# for Windows. I finally got through all obstacles like different endianities for BigIntegers in these two languages (Java: big endian, C#: little), so I successfuly made key-exchange as well. Now this is where problem comes, in Java I use AES/CBC/PKCS5Padding for encryption, but in C# there was no PKCS5 available, but as I read in other posts to this topic here on SO, PKCS7 is told to be same as PKCS5 or that Java really uses PKCS7 instead of PKCS5. I don't know what's correct.

这是代码:

using (System.Security.Cryptography.RijndaelManaged rijndael = new System.Security.Cryptography.RijndaelManaged())
{
    byte[] iv = new byte[16];
    for (int i = 0; i < 16; i++)
        iv[i] = 0;
    rijndael.Padding = PaddingMode.PKCS7;
    rijndael.Mode = CipherMode.CBC;
    rijndael.Key = Sys.PrivateKey;
    rijndael.KeySize = 128;
    rijndael.BlockSize = 128;
    rijndael.IV = iv;
    Sys.LogWrite("Decrypt input bytes length: " + buff.Length + ", keyLength: " + Sys.PrivateKey.Length);
    Sys.LogWriteBuffer("Input bytes", buff);
    Sys.LogWriteBuffer("Input key", Sys.PrivateKey);
    ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);
    buff=rijndael.CreateDecryptor().TransformFinalBlock(buff, 0, buff.Length);
    Sys.LogWriteBuffer("buffer: ", buff);
}

请忽略IV始终为00 00 00 00,这仅用于测试目的. 数据始终来自服务器,并且密钥在密钥交换中生成:

Please ignore that IV is always 00 00 00 00, this is only for testing purposes. Data come from server always and key is generated in key-exchange:

Decrypt input bytes length: 32, keyLength: 16
Input bytes: 7C 25 3F 49 9E D5 51 67 E2 86 F9 86 2E C1 8F 22 70 51 65 74 FC 39 2C 52 A6 83 36 B5 9A C7 27 B9 
Input key: 1C 13 C2 33 50 57 00 DB FD 60 E2 1C 27 2A A5 00 

如果我将其放在任何在线AES解密器中,例如 http://aes.online-domain- tools.com/我总是得到正确的结果:[[27,{"Established":true}]] 但是在C#中,我只能得到这个:

If I put it to any online AES decryptor like this http://aes.online-domain-tools.com/ I always get correct result: [[27,{"Established":true}]] But in C# I only get this:

System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed.
   at System.Security.Cryptography.RijndaelManagedTransform.DecryptData(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[]& outputBuffer, Int32 outputOffset, PaddingMode paddingMode, Boolean fLast)
   at System.Security.Cryptography.RijndaelManagedTransform.TransformFinalBlock(Byte[] inputBuffer, Int32 inputOffset, Int32 inputCount)

我什至尝试了PaddingMode.None,它没有引发任何异常,但是输出只是随机字节. 即使在线解密程序也能正确解决问题,我该怎么办?

I even tried PaddingMode.None, that didn't throw any exception, but output was just random bytes. What am I doing wrong when even online decryptor can solve it correctly?

其他应产生相同结果的示例输入数据[[27,{"Established":true}]]:

Other example input data which should produce same result [[27,{"Established":true}]]:

Decrypt input bytes length: 32, keyLength: 16
Input bytes: 85 5C 55 24 44 B8 77 A5 EF CE E7 A1 45 EC F3 84 2F 8B 74 1F AB D9 BE D0 82 64 BC 0D B0 50 73 63 
Input key: B2 21 FA 17 63 E6 4C 25 48 03 84 64 8B 70 05 00 

Decrypt input bytes length: 32, keyLength: 16
Input bytes: 8B FC 47 B4 91 05 B7 E1 6C 0E 61 78 D2 51 6B 77 EF 80 30 49 37 05 DA 79 47 52 D1 24 B9 DE A7 F3 
Input key: E7 BF E0 AA AC F1 26 42 06 D6 59 44 F9 33 74 63 

请注意,IV始终为16个空字节.

Notice that IV is always 16 null bytes.

推荐答案

我终于发现了这个问题,这真令人难以置信! 代替以这种方式创建解密器:

I finally found the issue and it's unbelievable! Instead of creating decryptor this way:

ICryptoTransform decryptor = rijndael.CreateDecryptor(rijndael.Key, rijndael.IV);

我应该以这种方式创建它:

I should have it created this way:

ICryptoTransform decryptor = rijndael.CreateDecryptor(Sys.PrivateKey, iv);

因此,如果将来有人遇到类似的问题,那么这里已经是广义函数:

So if anyone in future had similar problem, here is already generalized function:

        public static String Decrypt(byte[] buff, byte[] key, byte[] iv)
        {
            using (System.Security.Cryptography.RijndaelManaged rijndael = new System.Security.Cryptography.RijndaelManaged())
            {
                rijndael.Padding = PaddingMode.PKCS7;
                rijndael.Mode = CipherMode.CBC;
                rijndael.KeySize = 128;
                rijndael.BlockSize = 128;
                ICryptoTransform decryptor = rijndael.CreateDecryptor(key, iv);
                System.IO.MemoryStream memoryStream = new System.IO.MemoryStream(buff);
                CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
                byte[] output = new byte[buff.Length];
                int readBytes = cryptoStream.Read(output, 0, output.Length);
                return System.Text.Encoding.UTF8.GetString(output, 0, readBytes);
            }
        }

希望有帮助.

这篇关于AES解密失败,并显示“填充无效且无法删除".的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆