Add aes.Padding = PaddingMode.None;
in decryption method.
Why does AES decryptor always returns 16 zeros (in 16 bytes)?
-
21-07-2023 - |
Question
My goal is to get a very simple block cipher, that is, the Core of AES. It must take a key and a block and return a block. The decryptor should take the key and the block an return the original block.
I have been testing with the following key (in hex)
AA000000000000000000000000000000
and the following plain text
AA000000000000000000000000000000
(again in hex, and yes, the same as the key)
The result should be
814827A94525FF24B90F20BEC065866D
and indeed it is. (You can verify here that that should be the result at http://www.cryptogrium.com/aes-encryption-online-ecb.html with this as input and selecting AES-128).
But the decryptor always returns
00000000000000000000000000000000
(Only zeros).
What I'm I doing wrong in the following implementation? This implementation is only for educational purposes. That is why I used ECB mode and why I'm expecting always the same encryption.
namespace CryptographyCSharp
{
using System;
using System.Security.Cryptography;
public class MyAes
{
public static string EncryptStringToBytes_Aes(string msg_hex, string key_hex)
{
if (msg_hex == null)
throw new ArgumentNullException("msg_hex");
if (key_hex == null)
throw new ArgumentNullException("key_hex");
byte[] output = new byte[16];
msg_hex = msg_hex.PadRight(32, '0');
key_hex = key_hex.PadRight(32, '0');
using (var aes = Aes.Create("AES"))
{
aes.BlockSize = 128;
aes.KeySize = 128;
aes.Mode = CipherMode.ECB;
if (!aes.ValidKeySize(128))
{
throw new Exception();
}
ICryptoTransform encryptor = aes.CreateEncryptor(key_hex.hex2bytes(), null);
encryptor.TransformBlock(msg_hex.hex2bytes(), 0, 16, output, 0);
encryptor.Dispose();
}
return output.tohex();
}
public static string DecryptStringFromBytes_Aes(string hex_ct, string key_hex)
{
if (hex_ct == null)
throw new ArgumentNullException("cipherText");
if (key_hex == null)
throw new ArgumentNullException("Key");
hex_ct = hex_ct.PadRight(32, '0');
key_hex = key_hex.PadRight(32, '0');
string plaintext = null;
using (Aes aes = Aes.Create("AES"))
{
aes.BlockSize = 128;
aes.KeySize = 128;
aes.Mode = CipherMode.ECB;
if (!aes.ValidKeySize(128))
{
throw new Exception();
}
ICryptoTransform decryptor = aes.CreateDecryptor(key_hex.hex2bytes(), null);
var output = new byte[16];
decryptor.TransformBlock(hex_ct.hex2bytes(), 0, 16, output, 0);
plaintext = output.tohex();
}
return plaintext;
}
}
}
I have used some extension methods that transform hex to bytes and viceversa (that is string.hex2bytes and bytes[].tohex). I can provide them if you need them.
Solution
OTHER TIPS
The code you are running includes padding. Padding allows data that is not evenly divisible by the block size. In this example you are transforming a single block in which case you could change the padding mode to none
aes.Padding = PaddingMode.None
(as answered by Ulugbek Umirov)The
ICryptoTransform.TransformBlock()
function returns the number of bytes written to the output this can be less than the block size must accommodate that case.The
encryptor.TransformFinalBlock()
function should always be called last this may include additional bytes. This can be called with an empty byte array as input.
Given that you are only transforming a single block the simplest thing to do is to:
- Add
aes.Padding = PaddingMode.None
- Change the following line
encryptor.TransformBlock(msg_hex.hex2bytes(), 0, 16, output, 0);
to
output = encryptor.TransformFinalBlock(msg_hex.hex2bytes(), 0, 16);
Apologies for answering an old question but given that the current accepted answer is incomplete I thought it would be useful to provide the additional details.