简体   繁体   English

AES解密失败,并显示“填充无效且无法删除”

[英]AES decrypt fails with “Padding is invalid and cannot be removed”

I am making cross-platform application with server being written in Java, so I ended up with C# for Windows. 我使用服务器用Java编写跨平台应用程序,因此最终使用Windows的C#。 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. 最终,我克服了所有障碍,例如使用这两种语言的BigIntegers的字节序不同(Java:big endian,C#:little),因此我也成功进行了密钥交换。 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. 现在这是问题所在了,在Java中我使用AES/CBC/PKCS5Padding进行加密,但是在C#中没有可用的PKCS5, 但是正如我在SO上此主题的其他文章中所读到的那样,PKCS7被告知与PKCS5相同。或Java确实使用PKCS7而不是PKCS5。 I don't know what's correct. 我不知道什么是正确的。

So this is the code: 所以这是代码:

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);
}

Please ignore that IV is always 00 00 00 00, this is only for testing purposes. 请忽略IV始终为00 00 00 00,这仅用于测试目的。 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 

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

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)

I even tried PaddingMode.None, that didn't throw any exception, but output was just random bytes. 我什至尝试了PaddingMode.None,没有抛出任何异常,但是输出只是随机字节。 What am I doing wrong when even online decryptor can solve it correctly? 即使在线解密器也能正确解决问题,我在做什么错?

Other example input data which should produce same result [[27,{"Established":true}]] : 其他应产生相同结果的示例输入数据[[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 

Notice that IV is always 16 null bytes. 请注意,IV始终为16个空字节。

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);
            }
        }

Hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM