Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to decrypt an AES-256-CBC encrypted string

Tags:

c#

encryption

I'm new to C# and I really need help. I need to encrypt/decrypt a string with AES-256-CBC in C#, I found this to encrypt a string:

    public static string EncryptString(string message, string KeyString, string IVString)
    {
        byte[] Key = ASCIIEncoding.UTF8.GetBytes(KeyString);
        byte[] IV = ASCIIEncoding.UTF8.GetBytes(IVString);

        string encrypted = null;
        RijndaelManaged rj = new RijndaelManaged();
        rj.Key = Key;
        rj.IV = IV;
        rj.Mode = CipherMode.CBC;

        try
        {
            MemoryStream ms = new MemoryStream();

            using (CryptoStream cs = new CryptoStream(ms, rj.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
            {
                using (StreamWriter sw = new StreamWriter(cs))
                {
                    sw.Write(message);
                    sw.Close();
                }
                cs.Close();
            }
            byte[] encoded = ms.ToArray();
            encrypted = Convert.ToBase64String(encoded);

            ms.Close();
        }
        catch (CryptographicException e)
        {
            Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
            return null;
        }
        catch (UnauthorizedAccessException e)
        {
            Console.WriteLine("A file error occurred: {0}", e.Message);
            return null;
        }
        catch (Exception e)
        {
            Console.WriteLine("An error occurred: {0}", e.Message);
        }
        finally
        {
            rj.Clear();
        }
        return encrypted;
    }

I tried to write a decrypt function base on the above code, the following code is what I did:

  // Decrypt a byte array into a byte array using a key and an IV 
        private byte[] Decrypt(byte[] cipherData, byte[] Key, byte[] IV)
        {
            byte[] decryptedData;
            //string plaintext = null;
            //MemoryStream ms = new MemoryStream(cipherData);

            RijndaelManaged alg = new RijndaelManaged();
   alg.KeySize = 256;
            alg.BlockSize = 128;
            alg.Key = Key;
            alg.IV = IV;
            alg.Mode = CipherMode.CBC;
            alg.Padding = PaddingMode.Zeros;

            //Array.Copy(Key, 0, IV, 0, IV.Length);

            ICryptoTransform decryptor = alg.CreateDecryptor(alg.Key, alg.IV);

            using(MemoryStream ms = new MemoryStream(cipherData))
            {
                using (CryptoStream csDecrypt = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader sw = new StreamReader(csDecrypt))
                    {
                        sw.ReadToEnd();
                        sw.Close();
                    }

                    csDecrypt.Close();
                    decryptedData = ms.ToArray();
                }
            }

            //byte[] decryptedData = System.Text.Encoding.Unicode.GetBytes(plaintext);
            return decryptedData; 
        }

But it's nonsense, it can't decrypt anything. I'm really confused and need help. Thank you for any help!

P/s: Please don't give me other similar answered questions, I already take a look at them. Their encrypt function doesn't have the same output like the above encrypt function, while I need to decrypt string which MUST be encrypt by the above function. I have two friend who wrote decrypt function in PHP and objective-C, which matched with the above encrypt function, it's bad to have them do it again.

like image 255
Mee Avatar asked Nov 30 '13 07:11

Mee


1 Answers

Looking at your encryption, something like this should do it, passing the resulting string from your encryption in should give the original string back;

// Decrypt a string into a string using a key and an IV 
public static string Decrypt(string cipherData, string keyString, string ivString)
{
    byte[] key = Encoding.UTF8.GetBytes(keyString);
    byte[] iv  = Encoding.UTF8.GetBytes(ivString);

    try
    {
        using (var rijndaelManaged =
               new RijndaelManaged {Key = key, IV = iv, Mode = CipherMode.CBC})
        using (var memoryStream = 
               new MemoryStream(Convert.FromBase64String(cipherData)))
        using (var cryptoStream =
               new CryptoStream(memoryStream,
                   rijndaelManaged.CreateDecryptor(key, iv),
                   CryptoStreamMode.Read))
        {
            return new StreamReader(cryptoStream).ReadToEnd();
        }
    }
    catch (CryptographicException e)
    {
        Console.WriteLine("A Cryptographic error occurred: {0}", e.Message);
        return null;
    }
    // You may want to catch more exceptions here...
}

A small note; you're getting the key using UTF8 encoding from the key string, UTF8 encoding may give you multiple bytes back for international characters, which may give a key or IV of the wrong length for encryption/decryption. Also, using the small range of passwords/keys with 8 characters and printable characters will not give you very secure encryption, you may want to run the string though SHA1 or similar before using it as a key (which will sadly make it incompatible with the current encryption)

like image 57
Joachim Isaksson Avatar answered Sep 28 '22 00:09

Joachim Isaksson