3
votes

I'm trying to decrypt a file which was encrypted in Java program, allegedly using AES-256 CBC with default IV.

If I use general decryption method (DecryptAesCbc), the only first block is successfully decrypted.

If I use the suggested decryption method (Decrypt) from the Java developer, all the text is successfully decrypted + some appended characters at the end (probably padding?).

  1. If I understand correctly, the CBC cipher mode was not properly used (Visual example) because every single block is XOR-ed with IV and not with the previous ciphertext block?
  2. What is the best way of removing (and detecting) possible garbage bytes from the last block (garbage bytes values change from file to file) if I use method Decrypt? Should I just try to remove any repeated bytes from the end of the last block?

Working example: https://dotnetfiddle.net/M1zQbS

using System;
using System.IO;
using System.Net;
using System.Security.Cryptography;
using System.Text;

/* 
Original text:

It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).

Alleged encryption algorithm: AES CBC 256bit key (default IV) - file was encrypted in Java program.
*/

public class Program
{

    //BASE64 encoded cyphertext
    public static string encryptedFileBase64 = "k+8W4j0bec7AlcuxQ017lcSuZesp6hroADqN6nsYfMJyvpzrPQEGplGvcWd9Th7buerMkkpXYRGXJm+J4rVdwxi8nMZkithPrweUpHn27I/Td1ETuVJDQCfo/3ZG0/Hya/zvvq+A8YOgreC1qDkg/ap/Wci7RfVdBD1RXzhrLLD6PcdyZW34AWwjvGAnqrR5KLBeGxT6txTjx/V9SR21rD5LLz12QB4g6A6nulLfZiOHKhRydr9XpJzbISjjAh8/RAGDQHtEwdvbWngH/c7zmrZDL1gsC9e7Ia2wLeTQXSQkb6DAeb7XFyjHObX099xeMpjT9ZnELe/W1eCayC881iEoIVsB1mQA8FktOxyPHwDqU0cLMDjpLtu/1BzW838nCZEKExCKeRjeEDDtixU+KLl/BtDCXMGKXQPPaJk8gK9Ytb7+KCE+h4qAatUBydqIu9wtULu6qsk08S7tWhYHdDJiBToyizogNSUgsLQt89ssLYeb2Iof/ybHDXGi8UlgUohSuvzARUffhtYtmm4cljO92XdS+6bPOX7oW4Od3jPldXOnITZyj95lD3pZf2ss3xIan8UZ3MJNyIvnVR/FGqF/lBxyNIcbRWaMXheb+QBKEQsmphSrbR5AMdo7GsTSw32o7wJ1dqBrK0Sl5fsUjtY4ivV88TWqkoSsyT1XczDK8IsOgXFBGp/NxDcBrQV0HyTkN7AchNdVj7b5LRDwBOKag4jGwb87pyFdCjtAEd4XdS7asvMOoEBQNSL/B0NXFqWB5SyFHhHZYK7ewT9P38zsB8zHxYDcfaSujwmaS5YOVw8/ltO3qQfy02zy/3K+";
    //BASE64 encoded AES key
    public static string aesKeyBase64 = "lAw0kowr1i//T6Bci78bRX/lIRIwwKeGUz4pHDz0jjo=";

    public static string encryptedFileBase64_2 = "0S0tQ2jupE7bHbVspWCOOSWs/hEm/da+oFSVEU1XkzenZmb+OXWM7+4WUNAUU2hZ4IWJULl34Ha8pIb2btLOuv+KSOmFG5wX+rRMd2y66/HLDcHgOkZUPG3c+MV6261q3U2cFad6kZzRx1td3eXiD2vNljP1VKT1Fcr2c8sVVH2Fo1tQEm21YAjxgvcl3k6r6B0zigL1iAYH5liC65LQLihUyrcPLZ7vy2Wt2tKeFUE/kVXwX9/KHQEsY+j9HCE8zPEGkjieimxY8uaxKvEZBVYZ1EAT92YIpOAaVOX8q61uQOurXqJFJ2COLD3MXH0/Cnp3aSQll/l2LmfiS396JbHw6NYn7GC+2eGiMbXeQs0Wo7b17hkQeSLtsB8U+Wdx";
    public static string aesKeyBase64_2 = "TL9wAPaCWj53zdbAVDdrtpAUtlKxDtySI4QtKQ5KstA=";

    public static void Main()
    {
        byte[] key = Convert.FromBase64String(aesKeyBase64);
        //IV
        byte[] iv = new byte[16] { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };

        Console.WriteLine("------------------First file-----------------\n\n");
        string decrypted = AesUtils.Decrypt(Convert.FromBase64String(encryptedFileBase64), key, iv);
        Console.WriteLine("------------------Proposed decryption process-----------------");
        Console.WriteLine(decrypted);

        Console.WriteLine("\n---------------AES CBC decryption process--------------------");
        string decrypted2 = AesUtils.DecryptAesCbc(Convert.FromBase64String(encryptedFileBase64), key, iv);
        Console.WriteLine(decrypted2);


        Console.WriteLine("\n\n------------------Second file-----------------\n\n");
        key = Convert.FromBase64String(aesKeyBase64_2);

        decrypted = AesUtils.Decrypt(Convert.FromBase64String(encryptedFileBase64_2), key, iv);
        Console.WriteLine("------------------Proposed decryption process-----------------");
        Console.WriteLine(decrypted);

        Console.WriteLine("\n---------------AES CBC decryption process--------------------");
        decrypted2 = AesUtils.DecryptAesCbc(Convert.FromBase64String(encryptedFileBase64_2), key, iv);
        Console.WriteLine(decrypted2);
    }
}


public static class AesUtils
{
    public static string Decrypt(byte[] cipherBytes, byte[] key, byte[] iv)
    {
        using (Aes encryptor = GetCryptoAlgorithm())
        {

            encryptor.Key = key;
            encryptor.IV = iv;

            using (MemoryStream memoryStream = new MemoryStream(cipherBytes.Length))
            {
                string plainText = String.Empty;


                for (int i = 0; i < cipherBytes.Length; i = i + 16)
                {
                    encryptor.IV = iv;
                    ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();
                    CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);
                    cryptoStream.Write(cipherBytes, i, 16);
                    cryptoStream.FlushFinalBlock();
                }
                byte[] plainBytes2 = memoryStream.ToArray();
                plainText = Encoding.UTF8.GetString(plainBytes2, 0, plainBytes2.Length);

                return plainText;
            }
        }
    }

    public static string DecryptAesCbc(byte[] inputArray, byte[] key, byte[] iv)
    {
        using (Aes aes = GetCryptoAlgorithm())
        {
            aes.Key = key;
            aes.IV = iv;

            ICryptoTransform cTransform = aes.CreateDecryptor();
            byte[] resultArray = cTransform.TransformFinalBlock(inputArray, 0, inputArray.Length);
            aes.Clear();

            return Encoding.UTF8.GetString(resultArray);
        }
    }

    private static Aes GetCryptoAlgorithm()
    {
        Aes algorithm = Aes.Create();
        algorithm.Padding = PaddingMode.None;
        algorithm.Mode = CipherMode.CBC;
        algorithm.KeySize = 256;
        algorithm.BlockSize = 128;

        return algorithm;
    }
}
1
It seems that the encryption is ECB+IV and this is neither ECB nor CBC, Just a new mode of operation. In CBC and ECB padding is required.kelalaka
Does the gabage(padding) characters are same? In PKCS#7 the added values are just the number of bytes that are added. as 01 or 02 02 or 03 03 03 or 04 04 04 04, etckelalaka
@kelalaka they are, thank you for explanationpunxrok

1 Answers

1
votes

The encryption is AES in ECB mode with PKCS7-padding.

If you use this configuration it will decrypt correctly and remove the padding:

private static Aes GetCryptoAlgorithm()
{
    Aes algorithm = Aes.Create();
    algorithm.Padding = PaddingMode.PKCS7;
    algorithm.Mode = CipherMode.ECB;
    algorithm.KeySize = 256;
    algorithm.BlockSize = 128;

    return algorithm;
}