sakthi
sakthi

Reputation: 57

AES to encrypt a single block shows error

when run below program it shows error.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Security.Cryptography;
using System.Web.UI.WebControls;
using System.Configuration;
using System.Text;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            //Your code goes here
            Console.WriteLine("Hello, world!");

            byte[] plainText = UTF8Encoding.UTF8.GetBytes("textt");
            byte[] key = UTF8Encoding.UTF8.GetBytes("1234567890123456");
            AES_encrypt_block(plainText,key);
        }
        private static byte[] AES_encrypt_block(byte[] plainText, byte[] Key)
        {
        byte[] output_buffer = new byte[plainText.Length];

        using (AesManaged aesAlg = new AesManaged())
        {
        //If CBC, must initialize IV = O_{128}
        //aesAlg.Mode = CipherMode.CBC;
        //aesAlg.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        aesAlg.Mode = CipherMode.ECB;

        aesAlg.BlockSize = 128;
        aesAlg.KeySize = 128;
        aesAlg.Padding = PaddingMode.None;
        aesAlg.Key = Key;

        // Create a decrytor to perform the stream transform.
        ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
        encryptor.TransformBlock(plainText, 0, plainText.Length, output_buffer, 0);
        }

        return output_buffer;
    }
    }

}

ERROR

Exception in user code:

System.ArgumentException: Value was invalid. at >System.Security.Cryptography.RijndaelManagedTransform.TransformBlock(Byte[] >inputBuffer, Int32 inputOffset, Int32 inputCount, Byte[] outputBuffer, Int32 >outputOffset) at Rextester.Program.AES_encrypt_block(Byte[] plainText, Byte[] Key) at Rextester.Program.Main(String[] args)"

Upvotes: 2

Views: 1962

Answers (2)

Emre Kabaoglu
Emre Kabaoglu

Reputation: 13146

You should change it;

encryptor.TransformBlock(plainText, 0, plainText.Length, output_buffer, 0);

to

var output = encryptor.TransformFinalBlock(plainText, 0, plainText.Length);

and you should specify the PaddingMode;

aesAlg.Padding = PaddingMode.PKCS7;

Entire method looks like;

private static byte[] AES_encrypt_block(byte[] plainText, byte[] Key)
{
    using (AesManaged aesAlg = new AesManaged())
    {
        aesAlg.Mode = CipherMode.ECB;
        aesAlg.BlockSize = 128;
        aesAlg.KeySize = 128;
        aesAlg.Padding = PaddingMode.PKCS7;
        aesAlg.Key = Key;

        // Create a decrytor to perform the stream transform.
        ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
        return encryptor.TransformFinalBlock(plainText, 0, plainText.Length);
    }
}

If you use the TransformBlock, the input text length should be 16. Because it transform the encyrption per block. So, you should use TransformFinalBlock instead of it. Also, PaddingMode should be set for shorter message data block.

EDIT

To perform decryption;

private static byte[] AES_Decrypt_block(byte[] cipherText, byte[] Key)
{
    using (AesManaged aesAlg = new AesManaged())
    {
        aesAlg.Mode = CipherMode.ECB;
        aesAlg.BlockSize = 128;
        aesAlg.KeySize = 128;
        aesAlg.Padding = PaddingMode.PKCS7;
        aesAlg.Key = Key;
        ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
        return decryptor.TransformFinalBlock(cipherText, 0, cipherText.Length);
    }
}

Usage

byte[] plainText = UTF8Encoding.UTF8.GetBytes("textt");
byte[] key = UTF8Encoding.UTF8.GetBytes("1234567890123456");
var encrypted = AES_encrypt_block(plainText, key);
var decrypted = AES_Decrypt_block(encrypted, key);
Console.WriteLine(UTF8Encoding.UTF8.GetString(decrypted));

Upvotes: 1

Michael
Michael

Reputation: 2123

You can do it like this (example). But I recommend to use CBC instead of ECB. And, because of the padding, the decrypted block will always have the size of the block, even if the original content (5-byte-string) is shorter. So when creating the string, insert the string length before the real content (2nd example).

encrypting/decrypting ECB:

private static AesManaged Create(byte[] key)
{
    var aes = new AesManaged();

    aes.Mode = CipherMode.ECB;
    aes.BlockSize = 128;
    aes.KeySize = 128;
    aes.Padding = PaddingMode.Zeros;
    aes.Key = key;

    return aes;
}
private static byte[] AES_encrypt_block(byte[] plainText, byte[] key)
{
    using (AesManaged aes = Create(key))
    {
        var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
        return encryptor.TransformFinalBlock(plainText, 0, plainText.Length);
    }
}
private static byte[] AES_decrypt_block(byte[] plainText, byte[] key)
{
    using (AesManaged aesAlg = Create(key))
    {
        var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
        return decryptor.TransformFinalBlock(plainText, 0, plainText.Length);
    }
}

string-to-byte:

private static byte[] StringToBytes(string s)
{
    var length = BitConverter.GetBytes(s.Length);
    var raw = Encoding.UTF8.GetBytes(s);
    var full = new byte[sizeof(int) + raw.Length];

    Array.Copy(length, full, sizeof(int));
    Array.Copy(raw, 0, full, sizeof(int), raw.Length);

    return full;
}
private static string BytesToString(byte[] input)
{
    var length = BitConverter.ToInt32(input, 0);

    return Encoding.UTF8.GetString(input, sizeof(int), length);
}

verification:

var key = UTF8Encoding.UTF8.GetBytes("1234567890123456");
var plainBytes = StringToBytes("textt");
var encryptedBytes = AES_encrypt_block(plainBytes, key);
var decryptedBytes = AES_decrypt_block(encryptedBytes, key);
var decryptedString = BytesToString(decryptedBytes);

Upvotes: 3

Related Questions