Search code examples
c#unixencryptioncryptographysolaris

How to decrypt a file in C# that was encrypted on Unix/Solaris using AES-128


I have been supplied with a file that was encrypted on a Unix Solaris 10/SunOS 5.10 machine using the $encrypt method. I believe this to have been done using an aes algorithm.

I need to decrypt this file using C# on a windows machine. I have been supplied with a 16 byte symmetric key but I am unsure how to proceed.

Several code examples I've found mention an IV, block size, padding, cipher mode etc. Unfortunately, I do not know what these are and my research on the standard Unix encrypt method hasn't returned anything useful. I believe I have been supplied with everything I would need to decrypt this on Unix (although I do not have the means to test) - but need this to work on Windows with C#.

Files will be supplied periodically (with the same key), so I need a solution that will work on an on-going basis.

Any helps would be greatly appreciated.

Thanks.

UPDATE:

Thanks to @Maarten (see comments) I now have a working solution:

RijndaelManaged objAlgorithm = new RijndaelManaged();
//set the mode, padding and block size
objAlgorithm.Padding = PaddingMode.PKCS7;
objAlgorithm.Mode = CipherMode.CBC;
objAlgorithm.KeySize = 128;
objAlgorithm.BlockSize = 128;

byte[] key = File.ReadAllBytes(@"PATH_TO_KEY_FILE");
byte[] inputBytes = File.ReadAllBytes(@"PATH_TO_INPUT");

byte[] format = new byte[4];
byte[] iterations = new byte[4];
byte[] IV = new byte[objAlgorithm.BlockSize / 8];
byte[] salt = new byte[16];
byte[] cipherText = new byte[inputBytes.Length - format.Length - iterations.Length - IV.Length - salt.Length];

// Split the input array
Array.Copy(inputBytes, 0, format, 0, format.Length);
Array.Copy(inputBytes, format.Length, iterations, 0, iterations.Length);
Array.Copy(inputBytes, (format.Length + iterations.Length), IV, 0, IV.Length);
Array.Copy(inputBytes, (format.Length + iterations.Length + IV.Length), salt, 0, salt.Length);
Array.Copy(inputBytes, (format.Length + iterations.Length + IV.Length + salt.Length), cipherText, 0, cipherText.Length);

Byte[] outputBytes = cipherText;
string plaintext = string.Empty;

using (MemoryStream memoryStream = new MemoryStream(outputBytes))
{
    using (CryptoStream cryptoStream = new CryptoStream(memoryStream, objAlgorithm.CreateDecryptor(key, IV), CryptoStreamMode.Read))
    {
        using (StreamReader srDecrypt = new StreamReader(cryptoStream))
        {
            try
            {
                int iReadBytes = cryptoStream.Read(outputBytes, 0, outputBytes.Length);
                //plaintext = Encoding.UTF8.GetString(outputBytes,0,outputBytes.Length);

                byte[] finalBytes = new byte[iReadBytes];
                Array.Copy(outputBytes, 0, finalBytes, 0, iReadBytes);

                File.WriteAllBytes(DirectoryPath + strOriginalFileName.Replace(".out", ".xml"), finalBytes);
            }
            catch (Exception ex)
            {
                //Handle Error
            }
        }
    }
}

Solution

  • You'll have to use AES with CBC padding and PKCS#7 padding, source on docs.oracle.com/..../encrypt-1.html:

    Algorithms

    The supported algorithms are displayed with their minimum and maximum key sizes in the -l option. These algorithms are provided by the cryptographic framework. Each supported algorithm is an alias of the PKCS #11 mechanism that is the most commonly used and least restricted version of a particular algorithm type. For example, des is an alias to CKM_DES_CBC_PAD and arcfour is an alias to CKM_RC4. Algorithm variants with no padding or ECB are not supported.

    This tells you to expect CBC and PKCS#7 padding for AES as well.

    Furthermore, you'd have to parse the ciphertext structure that is output by encrypt (it has been defined as a stable interface which means it should not change between versions of encrypt:

    The output file of encrypt and the input file for decrypt contains the following information:

    • Output format version number, 4 bytes in network byte order. The current version is 1.

    • Iterations used in key generation function, 4 bytes in network byte order.

    • IV (ivlen bytes)[1]. iv data is generated by random bytes equal to one block size.

    • Salt data used in key generation (16 bytes).

    • Cipher text data.

    As the iterations and salt are not required for decryption using a key file I expect them to be either absent or zeroized.

    This should be enough information to decrypt in any environment that you control.