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.
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;
}
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.