C # AES Cryptography with MD5

2

I'm doing a college job where I need to encrypt a string with AES and Md5.

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

  

CryptographicException : The input data is not a complete block

What could this error be?

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;
    }
}

Encrypt 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 you generated from encryption:

    
asked by anonymous 23.11.2017 / 15:36

1 answer

3

Update

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

If you really need a string representation of the password, do 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 in .NET Fiddle

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

In the current code, you are passing the array with string into normal 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 shortened it so it would 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 in .NET Fiddle

    
23.11.2017 / 16:33