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.

Was it helpful?

Solution

Add aes.Padding = PaddingMode.None; in decryption method.

OTHER TIPS

  1. 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)

  2. 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.

  3. 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:

  1. Add aes.Padding = PaddingMode.None
  2. 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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top