1

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
            }
        }
    }
}
Martyn L
  • 21
  • 3
  • 1
    What have you tried? This question is off-topic without an attempt at solving the problem. IV, Block Size etc. can all be understood with a quick Google search. – Luke Joshua Park Mar 23 '17 at 10:39
  • 1
    *I believe this to have been done using an aes algorithm.* You "believe"? You need more information than that if you want to have any hope of decrypting your data. Do you even have the encryption key used to encrypt the data? – Andrew Henle Mar 23 '17 at 12:09
  • I have been supplied with a key and a Unix statement to decrypt the file: `$decrypt -v -a aes -k KEY_FILE -i encrypted_o16419394.out -o decrypted_o16419394.out` - which makes me 'believe' that it is encrypted using aes and since the KEY_FILE is 16 bytes long makes me 'believe' that it is aes-128. I've looked at [link](http://stackoverflow.com/questions/17511279/c-sharp-aes-decryption) and [link](http://stackoverflow.com/questions/19441640/how-can-i-encrypt-and-decrypt-using-aes-128-without-an-iv) but neither worked. – Martyn L Mar 23 '17 at 13:26
  • 1
    Could you put the information in your comment into the question along with some test key input and output (preferably hex encoded?). I'm wondering about the input and output size of the encrypt when you're using a key file, could you at least supply that? – Maarten Bodewes Mar 23 '17 at 19:40
  • It seems you have edited your question to include a solution. Please don't do this. You should post a solution as an answer to your own question and revert the question to an earlier revision – Artjom B. Apr 06 '17 at 19:59

2 Answers2

0

First, talk to whoever supplies the encrypted file and get more details from them.

Failing that make some assumptions and try things to see what happens.

You can probably assume that the IV is prepended to the cyphertext. You can probably assume that CBC mode was used or possibly GCM mode. Assume PKCS7 padding initially. Decrypting with NoPadding set will let you see what padding was used if PKCS7 doesn't work.

Be very careful not to use any system defaults since the defaults on the source machine may be different to yours. Explicitly specify everything including the end-of-line encoding for text since Unix differs from Microsoft there. Even small details can interfere with decryption.

rossum
  • 15,344
  • 1
  • 24
  • 38
  • Thanks @Rossum I have done that and will see what they come back with. I have already tried most combinations of mode and padding but I wonder now whether i'd missed the point of the IV. I was using the key for the IV also. If it's prepended, should I be extracting the first 16 bytes and using that as the IV and the remaining as the cyphertext? – Martyn L Mar 23 '17 at 14:51
  • Using the key as IV is extremely bad practice -- the key is secret, the IV isn't. Yes, remove the first 16 bytes as the IV and use it to decrypt the rest. – rossum Mar 23 '17 at 15:17
0

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.

Community
  • 1
  • 1
Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • I'll let you do the coding though. – Maarten Bodewes Mar 23 '17 at 19:37
  • Thanks @Maarten - you're a legend. That was the information I was missing - I've now parsed the input text and it works 'almost' perfectly. However, the decrypted string has 8 bytes at the end that I'm not expecting (not sure how to include the bytes in the post). I have been supplied the decrypted file for reference and can see that it has a blank line at the bottom - could that be the issue? That said, the file structure is XML with numerous line ends etc. that all work fine. I could ignore the last 8 bytes, but would prefer to understand why they are there. – Martyn L Mar 24 '17 at 10:07
  • I'd guess the PKCS#7 unpadding is still missing. To include the last - say 32 bytes - just copy then into a byte array and hex encode them. SO has a great Q/A on how to do that in C#. Then either post them as a comment here or edit them into the question. – Maarten Bodewes Mar 24 '17 at 10:10
  • Thanks for all your help with this @Maarten. Is this what you were after: 3E-0A-3C-2F-63-6F-6E-74-61-63-74-3E-0A-3C-2F-65-78-74-72-61-63-74-3E-0A-AB-EF-9E-E9-15-16-21-7A – Martyn L Mar 24 '17 at 10:38
  • I hope that that is the ciphertext and not the plaintext. We of course need the plaintext bytes to find out what's happening. That doesn't look that it contains anything like XML or characters. – Maarten Bodewes Mar 24 '17 at 10:43
  • That is the last 32 bytes of the decrypted text: 3E0A3C2F636F6E746163743E0A3C2F657874726163743E0AABEF9EE91516217A and this converts to: `> «ïžé!z` – Martyn L Mar 24 '17 at 11:06
  • That *does* look like random trash unfortunately. That's very strange considering the definition you got. For XML there is of course a way out: the end tag can be used to determine the size. But it is not what you *should* be receiving. There does seem to be a 0A value as well at the end (Unix end of line) but the trouble is that random padding can also contain this value. Somebody at the other end messed up, this is not PKCS#7 padding. – Maarten Bodewes Mar 24 '17 at 11:25
  • I've added my final code to the original question in case i'm doing something stupid which is causing the _trash_ data. Thanks again for all your help @Maarten - I thought I had a bad day ahead, but it's turned out pretty good. – Martyn L Mar 24 '17 at 13:17
  • You mean stupid things like ignoring the return value of the `Read` method causing it to return garbage in the buffer at the end of the plaintext? – Maarten Bodewes Mar 24 '17 at 13:26
  • That's exactly what I meant by stupid!! Thanks again, all sorted now. – Martyn L Mar 24 '17 at 13:58