C# AES encryption with MD5

Asked

Viewed 1,660 times

2

I’m doing a college paper where I need to encrypt a string with AES and Md5.

When I do the encryption, returns the normal result (I think), but when I go decrypt, returns the following error:

Cryptographicexception: Input data is not a complete block

What could be this mistake?

Codes:

class Encryptor
{
    //MD5
    public static string GerarHashMd5(string input)
    {
        MD5 md5Hash = MD5.Create();
        // Converter a String para array de bytes, que é como a biblioteca trabalha.
        byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));

        // Cria-se um StringBuilder para recompôr a string.
        StringBuilder sBuilder = new StringBuilder();

        // Loop para formatar cada byte como uma String em hexadecimal
        for (int i = 0; i < data.Length; i++)
        {
            sBuilder.Append(data[i].ToString("x2"));
        }

        return sBuilder.ToString();
    }

    //AES
    static public byte[] encryptdata(byte[] bytearraytoencrypt, string key, string iv)
    {
        AesCryptoServiceProvider dataencrypt = new AesCryptoServiceProvider();
        //Block size : Gets or sets the block size, in bits, of the cryptographic operation.  
        dataencrypt.BlockSize = 128;
        //KeySize: Gets or sets the size, in bits, of the secret key  
        dataencrypt.KeySize = 128;
        //Key: Gets or sets the symmetric key that is used for encryption and decryption.  
        dataencrypt.Key = System.Text.Encoding.UTF8.GetBytes(key);
        //IV : Gets or sets the initialization vector (IV) for the symmetric algorithm  
        dataencrypt.IV = System.Text.Encoding.UTF8.GetBytes(iv);
        //Padding: Gets or sets the padding mode used in the symmetric algorithm  
        dataencrypt.Padding = PaddingMode.PKCS7;
        //Mode: Gets or sets the mode for operation of the symmetric algorithm  
        dataencrypt.Mode = CipherMode.CBC;
        //Creates a symmetric AES encryptor object using the current key and initialization vector (IV).  
        ICryptoTransform crypto1 = dataencrypt.CreateEncryptor(dataencrypt.Key, dataencrypt.IV);
        //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.  
        byte[] encrypteddata = crypto1.TransformFinalBlock(bytearraytoencrypt, 0, bytearraytoencrypt.Length);
        crypto1.Dispose();
        //return the encrypted data  
        return encrypteddata;
    }

    //code to decrypt data
    static public byte[] decryptdata(byte[] bytearraytodecrypt, string key, string iv)
    {

        AesCryptoServiceProvider keydecrypt = new AesCryptoServiceProvider();
        keydecrypt.BlockSize = 128;
        keydecrypt.KeySize = 128;
        keydecrypt.Key = System.Text.Encoding.UTF8.GetBytes(key);
        keydecrypt.IV = System.Text.Encoding.UTF8.GetBytes(iv);
        keydecrypt.Padding = PaddingMode.PKCS7;
        keydecrypt.Mode = CipherMode.CBC;
        ICryptoTransform crypto1 = keydecrypt.CreateDecryptor(keydecrypt.Key, keydecrypt.IV);

        byte[] returnbytearray = crypto1.TransformFinalBlock(bytearraytodecrypt, 0, bytearraytodecrypt.Length);
        crypto1.Dispose();
        return returnbytearray;
    }
}

Encryption function:

private void criptografar_Click(object sender, EventArgs e)
{
    string key;
    string text;
    string iv = "HR$2pIjHR$2pIj12"; // aleatório
    string keyMd5;

    key = Senha.Text;
    keyMd5 = Encryptor.GerarHashMd5(key);
    key = "";

    text = Entrada.Text;
    byte[] textArray = Encoding.UTF8.GetBytes(text); // conversão pra encryptar
    byte[] encrypted = Encryptor.encryptdata(textArray, keyMd5, iv); // encryptador

    Saida.Text = Encoding.UTF8.GetString(encrypted);
}

Decryption function:

private void descriptografar_Click(object sender, EventArgs e)
{
    string key;
    string text;
    string iv = "HR$2pIjHR$2pIj12"; // aleatório
    string keyMd5;

    key = Senha.Text;
    keyMd5 = Encryptor.GerarHashMd5(key);
    key = "";

    text = Entrada.Text;
    byte[] textArray = Encoding.UTF8.GetBytes(text); // conversão pra encryptar
    byte[] decrypted = Encryptor.decryptdata(textArray, keyMd5, iv); // decryptador

    Saida.Text = Encoding.UTF8.GetString(decrypted);
}

And here is the result that generated the encryption:

inserir a descrição da imagem aqui

1 answer

4


Updating

The biggest problem with your approach is to convert the array of byte for string. Normalize data to a string will end up causing some to be lost.

If a representation is really needed in string from password, make the conversion to Base64.

I set the code to work correctly.

class Program
{
    private const string IV = "HR$2pIjHR$2pIj12";

    public static void Main()
    {
        var senha = "123";
        var entrada = "teste22";

        var cripto = criptografar(senha, entrada);
        var cripto64 = Convert.ToBase64String(cripto);
        WriteLine($"Representação em string (em base64) da criptografia: {cripto64}");

        var decrip = descriptografar(senha, cripto);
        WriteLine($"Texto original (pelo byte[]): {Encoding.UTF8.GetString(decrip)}");

        var bytes = Convert.FromBase64String(cripto64);
        var decBase64 = descriptografar(senha, bytes);
        WriteLine($"Texto original (string base64): {Encoding.UTF8.GetString(decBase64)}");
    }

    static byte[] criptografar(string senha, string entrada)
    {
        string keyMd5 = Encryptor.GerarHashMd5(senha);
        return Encryptor.encryptdata(Encoding.UTF8.GetBytes(entrada), keyMd5, IV);
    }

    static byte[] descriptografar(string senha, byte[] criptografado)
    {
        string keyMd5 = Encryptor.GerarHashMd5(senha);                      
        return Encryptor.decryptdata(criptografado, keyMd5, IV);
    }
}

See working on . NET Fiddle


The problem is that to do the reverse process you need to pass as the first parameter of decryptData the array of bytes of encrypted text:

In the current code, you are passing the array with the string in plain text, see:

byte[] textArray = Encoding.UTF8.GetBytes(text); // GetBytes da entrada
byte[] decrypted = Encryptor.decryptdata(textArray, keyMd5, iv); // Tenta fazer o processo

The code should look like this (I gave a shortened to not be bad to read)

static void descriptografar_Click(string senha, string entrada)
{
    string iv = "HR$2pIjHR$2pIj12"; // aleatório
    string keyMd5 = Encryptor.GerarHashMd5(senha);

    WriteLine($"Hash MD5: {keyMd5}");

    byte[] textArray = Encoding.UTF8.GetBytes(entrada); // GetBytes da entrada
    byte[] input = Encryptor.encryptdata(textArray, keyMd5, iv); // criptografa a entrada
    byte[] decrypted = Encryptor.decryptdata(input, keyMd5, iv); // fazer o processo

    WriteLine($"Saida.Text: {Encoding.UTF8.GetString(decrypted)}");
}

See working on . NET Fiddle

Browser other questions tagged

You are not signed in. Login or sign up in order to post.