Search code examples
c#encryptionaes

How to byte[] from an encrypted string?


I am trying to encrypt and decrypt a string, and I can do it successfully. After that, I convert the encrypted byte[] to string to save in the database.

But when I try to convert the string back to byte[] again, my code throws an error.

To test the code I created a string variable to save the string encrypted.

the print error

How do I convert again the string back to byte[] successfully?

static void Main(string[] args)
{
    Console.WriteLine("Enter text that needs to be encrypted..");
    string data = Console.ReadLine();
    EncryptAesManaged(data);
    Console.ReadLine();
}

static void EncryptAesManaged(string raw)
{
    string EncryptionKey = "sruohfaymonerishfiahbihbgrG546";
    byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(raw);

    try
    {
        using (AesManaged aes = new AesManaged())
        {
            Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
            var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(EncryptionKey);

            aes.Key = pdb.GetBytes(32);
            aes.IV = pdb.GetBytes(16);
            // Encrypt string    
            byte[] encrypted = Encrypt(raw, aes.Key, aes.IV);

            // Print encrypted string    
            string passe = System.Text.Encoding.UTF8.GetString(encrypted);
            Console.WriteLine($"Encrypt:{passe}");
            Console.WriteLine(System.Text.Encoding.UTF8.GetBytes(passe));

            // Decrypt the bytes to a string.    
            string decrypted = Decrypt(System.Text.Encoding.UTF8.GetBytes(passe), aes.Key, aes.IV);
            // Print decrypted string. It should be same as raw data    
            Console.WriteLine($"Decrypted data: {decrypted}");
        }
    }
    catch (Exception exp)
    {
        Console.WriteLine(exp.Message);
    }

    Console.ReadKey();
}

static byte[] Encrypt(String plainText, byte[] Key, byte[] IV)
{
    byte[] encrypted;

    using (AesManaged aes = new AesManaged())
    {
        // Create encryptor    
        ICryptoTransform encryptor = aes.CreateEncryptor(Key, IV);

        // Create MemoryStream    
        using (MemoryStream ms = new MemoryStream())
        {
            // Create crypto stream using the CryptoStream class. This class is the key to encryption    
            // and encrypts and decrypts data from any given stream. In this case, we will pass a memory stream    
            // to encrypt    
            using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
            {
                // Create StreamWriter and write data to a stream    
                using (StreamWriter sw = new StreamWriter(cs))
                    sw.Write(plainText);

                encrypted = ms.ToArray();
            }
        }
    }

    return encrypted;
}

static string Decrypt(byte[] cipherText, byte[] Key, byte[] IV)
{
    string plaintext = null;
    // Create AesManaged    
    using (AesManaged aes = new AesManaged())
    {
        // Create a decryptor    
        ICryptoTransform decryptor = aes.CreateDecryptor(Key, IV);

        // Create the streams used for decryption.    
        using (MemoryStream ms = new MemoryStream(cipherText))
        {
            // Create crypto stream    
            using (CryptoStream cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
            {
                // Read crypto stream    
                using (StreamReader reader = new StreamReader(cs))
                    plaintext = reader.ReadToEnd();
            }
        }
    }

    return plaintext;
}

Solution

  • The problem is right here:

    string passe = System.Text.Encoding.UTF8.GetString(encrypted);
                   ^---------------------------------^
    

    and then here:

    string decrypted = Decrypt(System.Text.Encoding.UTF8.GetBytes(passe), aes.Key, aes.IV);
                               ^--------------------------------^
    

    I assume this is your simulation of storing it to the database and then getting it back, and storing it as a string.

    However, what you've done is almost certainly corrupted the string this way.

    Encoding.UTF8.GetString(bytes) does not convert a byte array containing arbitrary bytes to a string. Instead, it converts a byte array that is supposed to contain bytes making up an UTF8 encoded string back to that string.

    If the byte array contains arbitrary bytes, such as the result of encrypting text, this step and its companion Encoding.UTF8.GetBytes is almost certain to corrupt the data and/or lose bytes.

    Instead, you should use a different method of converting a byte array to a string and back.

    One way would be to use Base64 encoding, and you can replace the two lines above with this:

    string passe = Convert.ToBase64String(encrypted);
    ...
    string decrypted = Decrypt(Convert.FromBase64String(passe), aes.Key, aes.IV);
    

    This will result in your program encrypting and then decrypting the string just fine.


    Additionally, you might want to look into storing the bytes into your database directly. Depending on your database engine there might be good support for storing byte arrays directly, without mucking about with string conversions of any kind.