Ivan Fourie
Ivan Fourie

Reputation: 25

OpenSSL encryption failing to decrypt C#

I have been struggling with decrypting some data that is being encrypted on a Unix machine via SSL, I keep getting padding errors, and am unsure what it is that I am missing.

The encrypted file is a simple text file just saying "Hello World".

The encryption command used in unix is:

openssl enc -base64 -aes-256-cbc  -k 12345678901234567890123456789012 -in test.txt -out cbc64.txt

I have 2 methods that I am using to decrypt:

private static CipherMode sCipherMode = CipherMode.CBC;
private static PaddingMode sPaddingMode = PaddingMode.PKCS7;
private const int HigKeyLen = 32;
private const int HigKeySiz = 256;

public static string decrypt(string text, //the text to be decrypt                
    int cipherindex// the strength of the original encryption
    )
{
    byte[] plainText = null;
    try
    {
        string tempText = Regex.Replace(text, @"\n", "");
        //get the cipher strength--from cipherindex            
        CipherKey Key = CipherKey.getCipherKey(cipherindex);
        //build and init the Decryptor
        RijndaelManaged rijndaelCipher = new RijndaelManaged();
        rijndaelCipher.Mode = sCipherMode;
        rijndaelCipher.Padding = sPaddingMode;
        rijndaelCipher.KeySize = Key.Size;
        rijndaelCipher.BlockSize = Key.Size;
        byte[] encryptedData = Convert.FromBase64String(tempText);
        byte[] pwdBytes = System.Text.Encoding.UTF8.GetBytes(pass);
        byte[] keyBytes = new byte[Key.Len];


        int len = pwdBytes.Length;
        if (len > keyBytes.Length)
        {
            len = keyBytes.Length;
        }
        Array.Copy(pwdBytes, keyBytes, len);

        rijndaelCipher.Key = keyBytes;
        rijndaelCipher.IV = keyBytes;
        ICryptoTransform transform = rijndaelCipher.CreateDecryptor();
        plainText = transform.TransformFinalBlock(encryptedData, 0, encryptedData.Length);

    }
    catch (Exception e)
    {
        // test code, do nothing
    }
    return System.Text.Encoding.UTF8.GetString(plainText);
}

This returns the following error: Padding is invalid and cannot be removed.

The second method:

public static string Decryptor(string TextToDecrypt)
    {

        byte[] EncryptedBytes = Convert.FromBase64String(Regex.Replace(TextToDecrypt, @"\n", ""));

        //Setup the AES provider for decrypting.            
        AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider();
        //aesProvider.Key = System.Text.Encoding.ASCII.GetBytes(strKey);
        //aesProvider.IV = System.Text.Encoding.ASCII.GetBytes(strIV);
        aesProvider.BlockSize = 128;
        aesProvider.KeySize = 256;
        //My key and iv that i have used in openssl
        aesProvider.Key = System.Text.Encoding.UTF8.GetBytes(pass);
        aesProvider.IV = System.Text.Encoding.UTF8.GetBytes(pass);
        aesProvider.Padding = PaddingMode.PKCS7;
        aesProvider.Mode = CipherMode.CBC;

        ICryptoTransform cryptoTransform = aesProvider.CreateDecryptor(aesProvider.Key, aesProvider.IV);
        byte[] DecryptedBytes = cryptoTransform.TransformFinalBlock(EncryptedBytes, 0, EncryptedBytes.Length);
        return System.Text.Encoding.ASCII.GetString(DecryptedBytes);
    }

The second method gives an issue due to the password not being the right length for the blocksize.

What is it that I am doing wrong?

Upvotes: 0

Views: 1234

Answers (1)

gusto2
gusto2

Reputation: 12085

You openssl command is wrong, I assume it should be:
openssl enc -base64 -aes-256-cbc -k 12345678901234567890123456789012 -in test.txt -out cbc64.txt

reading your code I see you made a few wrong assumptions:

  • You are using the password as a key and as IV (where did you get that?) Password is not key
  • you've assumed the output is pure ciphertext

try to add -p parameter to the openssl enc command and it will display as well salt and derived key and iv

So lets fix that:

  1. OpenSSL generates random 8 bytes salt
  2. OpenSSL uses its "magic" function EVP_BytesToKey to derive the key and IV from the passsword and salt, example impl in c#
  3. OpenSSL output looks like: base64(Salted_{salt}{ciphertext})

Upvotes: 1

Related Questions