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.
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. 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:
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. 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}]]:
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.
byte buff[]which is parsed from TCP Recv. As in example given above (Input bytes, Input key), input data are absolutely valid and decrypting them works even in online AES decryptor provided above and Java client too.TransformFinalBlockmight work but read the API specification: "TransformFinalBlock is a special function for transforming the last block or a partial block in the stream. It returns a new array that contains the remaining transformed bytes. A new array is returned, because the amount of information returned at the end might be larger than a single block when padding is added.". Using just this method is hacking, not coding.