I'm trying to use AesCryptoProvider to encrypt and decrypt byte arrays.
Here are my encrypt and decrypt methods:
public static byte[] EncryptAes(byte[] data, out byte[] key, out byte[] iv)
{
if (data == null || data.Length <= 0)
throw new ArgumentNullException("data");
try
{
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.KeySize = 256;
aesAlg.BlockSize = 128;
aesAlg.Padding = PaddingMode.PKCS7;
aesAlg.Mode = CipherMode.CBC;
aesAlg.GenerateKey();
aesAlg.GenerateIV();
key = aesAlg.Key;
iv = aesAlg.IV;
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, aesAlg.CreateEncryptor(), CryptoStreamMode.Write))
{
csEncrypt.Write(data, 0, data.Length);
}
return msEncrypt.ToArray();
}
}
}
catch (CryptographicException e)
{
Log.Error(e);
key = null;
iv = null;
return null;
}
}
public static byte[] DecryptAes(byte[] encryptedData, byte[] key, byte[] iv)
{
if (encryptedData == null || encryptedData.Length <= 0)
throw new ArgumentNullException("encryptedData");
if (key == null || key.Length <= 0)
throw new ArgumentNullException("key");
if (iv == null || iv.Length <= 0)
throw new ArgumentNullException("iv");
try
{
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.KeySize = 256;
aesAlg.BlockSize = 128;
aesAlg.Padding = PaddingMode.PKCS7;
aesAlg.Mode = CipherMode.CBC;
aesAlg.Key = key;
aesAlg.IV = iv;
using (MemoryStream msDecrypt = new MemoryStream(encryptedData))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, aesAlg.CreateDecryptor(), CryptoStreamMode.Write))
{
csDecrypt.Write(encryptedData, 0, encryptedData.Length);
}
return msDecrypt.ToArray();
}
}
}
catch (CryptographicException e)
{
Log.Error(e);
return null;
}
}
Then to test it, I'm using this code:
originalMessage = "This is a test message.";
originalData = System.Text.Encoding.UTF8.GetBytes(originalMessage);
byte[] key, iv;
byte[] encryptedData = Encryption.EncryptAes(originalData, out key, out iv);
byte[] decryptedData = Encryption.DecryptAes(encryptedData, key, iv);
string decryptedMessage = System.Text.Encoding.UTF8.GetString(decryptedData);
Log.Debug(decryptedMessage); // This is a test message.?{?o?}??
The log output shows that the decrypted message has a bunch of garbage characters "?{?o?}??" at the end.
I've seen similar questions, but their answers don't seem to help. I've tried writing to another array during decryption like this:
using (MemoryStream msDecrypt = new MemoryStream(encryptedData))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, aesAlg.CreateDecryptor(), CryptoStreamMode.Write))
{
byte[] decryptedData = new byte[encryptedData.Length];
csDecrypt.Write(decryptedData, 0, decryptedData.Length);
}
return msDecrypt.ToArray();
}
But that results in this exception:
System.Security.Cryptography.CryptographicException: Padding is invalid and cannot be removed.
So there's gotta be something I'm missing. Any ideas? Thanks!
Yeah, reusing buffers is biting you. You generally don't expect the encrypted and decrypted data to be the same sizes, so reusing a buffer causes you to see left-over encrypted data in the decrypted data.
Make your decrypt similar to encrypt. Don't pass the buffer to the constructor of MemoryStream, let it allocate a buffer of the correct size:
using (MemoryStream msDecrypt = new MemoryStream())
{
using (CryptoStream csDecrypt =
new CryptoStream(msDecrypt,
aesAlg.CreateDecryptor(),
CryptoStreamMode.Write))
{
csDecrypt.Write(encryptedData, 0, encryptedData.Length);
}
return msDecrypt.ToArray();
}
I've tried writing to another array during decryption like this:
using (MemoryStream msDecrypt = new MemoryStream(encryptedData))
{
using (CryptoStream csDecrypt =
new CryptoStream(msDecrypt,
aesAlg.CreateDecryptor(),
CryptoStreamMode.Write))
{
byte[] decryptedData = new byte[encryptedData.Length];
csDecrypt.Write(decryptedData, 0, decryptedData.Length);
}
return msDecrypt.ToArray();
}
No read it back to yourself. You're still configuring the cryptostream to write rather than read. What you're doing here is allocating a new buffer and then telling AES to decrypt that empty buffer into the memory stream which was initialized with the encrypted data.
Related
I'm encrypting a string in .Net C#, sending it over using HttpRequest and decrypting it in .Net CF 3.5. Encrypting goes ok, but I get an error when decrypting the string.
Encrypting code:
public string Encrypt(string s)
{
byte[] encrypted;
using (RijndaelManaged myRijndael = new RijndaelManaged())
{
//myRijndael.GenerateKey();
myRijndael.Mode = CipherMode.ECB;
myRijndael.KeySize = 256;
myRijndael.Key = Encoding.ASCII.GetBytes(keystring);
//myRijndael.GenerateIV();
myRijndael.IV = Encoding.ASCII.GetBytes(IVstring);
encrypted = EncryptStringToBytes(s, myRijndael.Key, myRijndael.IV);
string x = Encoding.UTF8.GetString(encrypted);
}
return Encoding.UTF8.GetString(encrypted);
}
private byte[] EncryptStringToBytes(string plainText, byte[] Key, byte[] IV)
{
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Key = Key;
rijAlg.IV = IV;
ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return encrypted;
}
Decrypting code in CF 3.5:
public string Decrypt(string toDecrypt)
{
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(keystring);
byte[] keyIV = UTF8Encoding.UTF8.GetBytes(IVstring);
byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
RijndaelManaged rDel = new RijndaelManaged();
rDel.Key = keyArray;
rDel.KeySize = 256;
rDel.Mode = CipherMode.ECB;
rDel.Padding = PaddingMode.PKCS7;
ICryptoTransform cTransform = rDel.CreateDecryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
return Encoding.ASCII.GetString(resultArray, 0, resultArray.Length);
}
The line byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length); throws error : base {System.SystemException} = {"Length of the data to decrypt is invalid."}
I tried playing around with Padding etc, but to no avail. Thanks for your input.
EDIT
As suggested, I tried to use CryptoStream, but to no avail.
static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
{
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
string plaintext = null;
using (RijndaelManaged rijAlg = new RijndaelManaged())
{
rijAlg.Mode = CipherMode.ECB;
rijAlg.KeySize = 256;
rijAlg.Key = Key;
rijAlg.IV = IV;
ICryptoTransform decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
Now I get error:
base {System.ArgumentException} = {"Value can not be null.\r\nParameter name: inputBuffer"} at line plaintext = srDecrypt.ReadToEnd();
I want to do AES256 Encryption in .net core 1.1. RijndaelManaged is not supporting with the .net core 1.1. So I'm using here AES aes = new AES.create()
This part of code create the random private key for the encryption
public string GenaratePassPharse()
{
RandomNumberGenerator rngCryptoServiceProvider = RandomNumberGenerator.Create();
byte[] randomBytes = new byte[KEY_SIZE];
rngCryptoServiceProvider.GetBytes(randomBytes);
string plainPassPharse = Convert.ToBase64String(randomBytes);
return plainPassPharse;
}
and here the AES() encryption method. What I want to do is pass my generated key (which is return from above method)instead of the aesAlg.Key as an encryption key.
static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
aesAlg.BlockSize = 128;
aesAlg.KeySize = 128;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
And any another way to use AES256 Encryption algorithms?
The full code should be:
public static byte[] EncryptStringToBytes_Aes(string plainText, byte[] key, byte[] iv = null)
{
// Check arguments.
if (plainText == null)
{
throw new ArgumentNullException("plainText");
}
if (key == null || key.Length == 0)
{
throw new ArgumentNullException("Key");
}
// Create an Aes object
// with the specified key and IV.
using (Aes aes = Aes.Create())
{
aes.Key = key;
if (iv == null)
{
iv = new byte[aes.BlockSize / 8];
using (RandomNumberGenerator rngCryptoServiceProvider = RandomNumberGenerator.Create())
{
rngCryptoServiceProvider.GetBytes(iv);
}
}
// Note that we are setting IV, Mode, Padding
aes.IV = iv;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
// Create an encryptor to perform the stream transform.
using (ICryptoTransform encryptor = aes.CreateEncryptor())
using (MemoryStream ms = new MemoryStream())
using (CryptoStream cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
// Prepend the IV
cs.Write(iv, 0, iv.Length);
// Here we are setting the Encoding
using (StreamWriter sw = new StreamWriter(cs, Encoding.UTF8))
{
// Write all data to the stream.
sw.Write(plainText);
}
byte[] encrypted = ms.ToArray();
return encrypted;
}
}
}
public static string DecryptBytesToString_Aes(byte[] encrypted, byte[] key)
{
// Check arguments.
if (encrypted == null || encrypted.Length == 0)
{
throw new ArgumentNullException("plainText");
}
if (key == null || key.Length == 0)
{
throw new ArgumentNullException("Key");
}
// Create an Aes object
// with the specified key and IV.
using (Aes aes = Aes.Create())
{
aes.Key = key;
using (MemoryStream ms = new MemoryStream(encrypted))
{
// Read the prepended IV
var iv = new byte[aes.BlockSize / 8];
ms.Read(iv, 0, iv.Length);
// Note that we are setting IV, Mode, Padding
aes.IV = iv;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
// Create an encryptor to perform the stream transform.
using (ICryptoTransform decrytor = aes.CreateDecryptor())
using (CryptoStream cs = new CryptoStream(ms, decrytor, CryptoStreamMode.Read))
// Here we are setting the Encoding
using (StreamReader sr = new StreamReader(cs, Encoding.UTF8))
{
// Read all data from the stream.
string plainText = sr.ReadToEnd();
return plainText;
}
}
}
}
public static byte[] GenerateAesKey(int bits)
{
using (RandomNumberGenerator rngCryptoServiceProvider = RandomNumberGenerator.Create())
{
byte[] key = new byte[bits / 8];
rngCryptoServiceProvider.GetBytes(key);
return key;
}
}
public static void Main()
{
var key = GenerateAesKey(256);
var encrypted = EncryptStringToBytes_Aes("Hello", key);
var decrypted = DecryptBytesToString_Aes(encrypted, key);
}
This code prepend a random IV to the encrypted stream, and the recovers it from the encrypted stream to decrypt the stream.
It is very important that when you speak of encryption you set everything that can be setted. There must be no questions open. The encryption Mode, the Padding, the Encoding the plaintext must be encoded. Everything!
I am new to encryption concept. Am trying to use AES encryption to encrypt a file which seems to be working fine. But when I use the decryption, I get no errors but the data is not decrypted. The decryption code is below
public static string DecryptData(string sFileInPath, byte[] Key, byte[] IV)
{
String data = null;
byte[] file = File.ReadAllBytes(sFileInPath);
if (!File.Exists(sFileInPath))
throw new ArgumentNullException("FilenotExists");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
try
{
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.Padding = PaddingMode.None;
aesAlg.Key = Key;
aesAlg.IV = IV;
aesAlg.Mode = CipherMode.CBC;
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
MemoryStream ms = new MemoryStream();
using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
{
cs.Write(file, 0, file.Length);
cs.Close();
}
data = Encoding.Unicode.GetString(ms.ToArray());
msDecrypt.Close();
}
return data;
}
catch (Exception ex)
{
string status = string.Format("{0}: {1}", statustype.Failed.ToString(), ex.ToString());
return status;
}
}
Call to the decrypt method is
AesCryptoServiceProvider oAes = new AesCryptoServiceProvider();
string xml = Utility.DecryptData_AES(sfile,oAes.Key,oAes.IV);
Encryption method:
public static byte[] EncryptData(AlertEnvelope alertenvelope, byte[] Key, byte[] IV)
{
if (alertenvelope == null)
throw new ArgumentNullException("alertenvelope");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
byte[] encrypted;
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.Padding = PaddingMode.PKCS7;
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(alertenvelope);
}
encrypted = msEncrypt.ToArray();
}
}
}
return encrypted;
}
I will appreciate if someone can help me understand why the data is not being decrypted
I am trying to encrypt bytes with Aes. However, the output I get is really weird. Here is my functions (encrypt and decrypt). Am I doing something wrong?
public static byte[] encryptStream(byte[] plain, byte[] Key, byte[] IV)
{
byte[] encrypted; ;
using (MemoryStream mstream = new MemoryStream())
{
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
{
using (CryptoStream cryptoStream = new CryptoStream(mstream,
aesProvider.CreateEncryptor(Key, IV), CryptoStreamMode.Write))
{
cryptoStream.Write(plain, 0, plain.Length);
}
}
encrypted = mstream.ToArray();
}
return encrypted;
}
public static byte[] decryptStream(byte[] encrypted, byte[] Key, byte[] IV)
{
byte[] plain;
using (MemoryStream mStream = new MemoryStream())
{
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
{
using (CryptoStream cryptoStream = new CryptoStream(mStream,
aesProvider.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
{
cryptoStream.Read(encrypted, 0, encrypted.Length);
}
}
plain = mStream.ToArray();
}
return plain;
}
The issue is in your decryptStream() method, when you read from the cryptoStream you read INTO the encrypted buffer. When you call Read() you are already reading from the encrypted buffer because you wrapped it with the memory stream. You want to read into a NEW buffer which concatenated together will be the decrypted bytes.
public static byte[] decryptStream(byte[] encrypted, byte[] Key, byte[] IV)
{
byte[] plain;
byte[] buffer = new byte[32768];
int totalRead = 0;
MemoryStream plainStream = new MemoryStream();
using (MemoryStream mStream = new MemoryStream(encrypted))
{
using (AesCryptoServiceProvider aesProvider = new AesCryptoServiceProvider())
{
using (CryptoStream cryptoStream = new CryptoStream(mStream,
aesProvider.CreateDecryptor(Key, IV), CryptoStreamMode.Read))
{
while (true)
{
int read = cryptoStream.Read(buffer, 0, encrypted.Length);
if (read == 0)
break;
else
plainStream.Write(buffer, totalRead, read);
totalRead += read;
}
}
}
plain = plainStream.ToArray();
}
return plain;
}
I am banging my head to the wall.
I have the following Perl code, and I am trying to do this in .NET without success:
my $cipher = Crypt::CBC->new(
-iv => $iv,
-literal_key => 1,
-key => $key,
-cipher => "Crypt::OpenSSL::AES",
-blocksize => length($iv),
-keysize => length($key),
-header => "none"
);
my .net code is:
byte[] iv = new byte[] { 0x01,..... };
byte[] key = new byte[] { 0x01..... };
RijndaelManaged aes = new RijndaelManaged();
aes.Key = key;
aes.IV = iv;
encryptStringToBytes_AES("bla bla bla", aes.KEY, aes.IV)
...
static byte[] encryptStringToBytes_AES(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("Key");
// Declare the stream used to encrypt to an in memory
// array of bytes.
MemoryStream msEncrypt = null;
// Declare the RijndaelManaged object
// used to encrypt the data.
RijndaelManaged aesAlg = null;
try
{
// Create a RijndaelManaged object
// with the specified key and IV.
aesAlg = new RijndaelManaged();
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
msEncrypt = new MemoryStream();
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
}
}
finally
{
// Clear the RijndaelManaged object.
if (aesAlg != null)
aesAlg.Clear();
}
// Return the encrypted bytes from the memory stream.
return msEncrypt.ToArray();
}
What am i doing wrong???
Thanks!
Try with this:
UnicodeEncoding UE = new UnicodeEncoding();
byte[] bfr;
byte[] pwdBits = UE.GetBytes(plainText);
byte[] result;
int extends = (1 + (pwdBits.Length / 16)) * 16;
bfr = new byte[extends];
pwdBits.CopyTo(bfr, 0);
using (MemoryStream msCrypt = new MemoryStream())
{
RijndaelManaged RMCrypto = new RijndaelManaged();
RMCrypto.Padding = PaddingMode.PKCS7;
using (ICryptoTransform encriptor = RMCrypto.CreateEncryptor(Key, IV))
{
using (CryptoStream cs = new CryptoStream(msCrypt, encriptor, CryptoStreamMode.Write))
{
cs.Write(bfr, 0, bfr.Length);
cs.FlushFinalBlock();
result = msCrypt.ToArray();
cs.Close();
}
msCrypt.Close();
}
}
return result;