I get error "the input data is not a complete block", I dont know if my code is wrong or something is missing. i try to encrypt/decrypt bytes with same lenght.
=byte[] plain => MyEnc(plain) => byte[] encrypted => MyDec(encrypt) => byte[] plain
Plain and encrypted have the same length.
This is my encryption code:
public static byte[] MyEnc(byte[] Input)
{
byte[] inputencdec = Input;
byte[] encrypted;
using (MemoryStream mstream = new MemoryStream())
{
using (AesCryptoServiceProvider encdec = new AesCryptoServiceProvider())
{
encdec.BlockSize = 128;
encdec.KeySize = 256;
encdec.Key = ASCIIEncoding.ASCII.GetBytes(Key);
encdec.IV = ASCIIEncoding.ASCII.GetBytes(IV);
ICryptoTransform icrypt = encdec.CreateEncryptor(encdec.Key, encdec.IV);
using (CryptoStream cryptoStream = new CryptoStream(mstream,
icrypt, CryptoStreamMode.Write))
{
cryptoStream.Write(inputencdec, 0, inputencdec.Length);
}
}
encrypted = mstream.ToArray();
}
return encrypted;
}
this is my decryption code:
public static byte[] MyDec(byte[] Input)
{
byte[] inputencdec = Input;
byte[] buffer = new byte[Input.Length];
int totalRead = 0;
byte[] plain;
MemoryStream plainStream = new MemoryStream();
using (MemoryStream mStream = new MemoryStream(inputencdec))
{
using (AesCryptoServiceProvider encdec = new AesCryptoServiceProvider())
{
encdec.BlockSize = 128;
encdec.KeySize = 256;
encdec.Key = ASCIIEncoding.ASCII.GetBytes(Key);
encdec.IV = ASCIIEncoding.ASCII.GetBytes(IV);
ICryptoTransform icrypt = encdec.CreateDecryptor(encdec.Key, encdec.IV);
using (CryptoStream cryptoStream = new CryptoStream(mStream, icrypt, CryptoStreamMode.Read))
{
while (true)
{
int read = cryptoStream.Read(buffer, 0, inputencdec.Length);
if (read == 0)
break;
else
plainStream.Write(buffer, totalRead, read);
totalRead += read;
}
}
}
plain = plainStream.ToArray();
}
return plain;
}
Plain and encrypted are not the same length for CBC mode encryption, which you are using. The plaintext needs to be padded before it can be encrypted, so the ciphertext size is always larger than the plaintext message for CBC (which is the default mode that the decryptor is using).
Streaming modes do not need to expand the ciphertext as they do not require padding. Unfortunately Microsoft opted not to include counter mode in .NET. You could use CFB mode.
You could also decide to implement counter mode using ECB if you require parallel encryption (in the comments below the question). Generally AES is so fast nowadays that parallelism is not required. Implementing a statically sized counter and CTR buffer should pale in comparison with creating the multithreaded code.
This is incorrect and may cause an issue:
int read = cryptoStream.Read(buffer, 0, inputencdec.Length);
you should of course put in buffer.length, not inputencdec.length. The use of a buffer is to store data in a buffer, by reading up to buffer.length bytes per loop iteration.
This is incorrect as well:
plainStream.Write(buffer, totalRead, read);
the problem is that totalRead should be the offset in the buffer, not the offset within the stream. You're reading into offset 0 of the buffer, so you should start writing from offset 0 as well.
You could also create a MemoryStream for the plaintext, wrap it with a CryptoStream using a decryptor, and then write the ciphertext all in one go. There is no need for the encryption / decryption to use a different scheme, as far as I can see. You seem to keep all the plaintext / ciphertext in memory anyway.
Notes:
for CBC mode the IV should be random; it is often prefixed to the ciphertext and removed and used by the decryptor;
keys and IV's should consist of random bytes; they should not be strings.
Related
I have this code in CryptoJS, inside browser:
var decrypt = function (cipherText) {
var key = "a_long_key_goes_here";
var iv = "initial_vector_goes_here";
key = CryptoJS.enc.Hex.parse(key);
iv = CryptoJS.enc.Hex.parse(iv);
var decrypted = CryptoJS.TripleDES.decrypt({
ciphertext: CryptoJS.enc.Hex.parse(cipherText)
}, key, {
iv: iv,
mode: CryptoJS.mode.CBC
});
var clearText = decrypted.toString(CryptoJS.enc.Utf8);
return clearText;
};
This code is not written by me. Also the cipherText come from another server that I have no access to. However, I have access to key and to iv.
I can decrypt that cipherText inside a browser's console. But I want to use these keys to decrypt that cipherText inside C# code. Here's the code I've written:
public void Desrypt()
{
ICryptoTransform decryptor;
UTF8Encoding encoder;
string key = "a_long_key_goes_here";
string iv = "initial_vector_goes_here";
var cipherText = "cipher_text_goes_here";
string clearText = "";
byte[] cipherBytes = FromHexString(cipherText);
using (Aes aes = Aes.Create())
{
Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(key, new byte[] { });
aes.Key = pdb.GetBytes(32);
aes.IV = pdb.GetBytes(16);
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
clearText = Encoding.Unicode.GetString(ms.ToArray());
}
}
return clearText;
}
public static byte[] FromHexString(string hexString)
{
var bytes = new byte[hexString.Length / 2];
for (var i = 0; i < bytes.Length; i++)
{
bytes[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
}
return bytes;
}
I have some problems though. I don't understand if I'm correctly decoding the given cipherText from hexadecimal or not. Also I can't instantiate Rfc2898DeriveBytes, because I don't know what the second parameter (salt) should be.
Also I don't know where should I use that iv I've gotten from the CryptoJS code.
Could you please help?
So that both codes are compatible, the following changes of the C# code are necessary:
The return type of the Decrypt method must be changed from void to string.
Key and IV have to be decoded hexadecimal like the ciphertext with FromHexString.
Instead of AES, TripleDES must be used.
Rfc2898DeriveBytes implements PBKDF2 and must not be applied (since the JavaScript code does not use PBKDF2 either).
The decrypted data must not be decoded with Encoding.Unicode (which corresponds to UTF16LE in .NET), but with Encoding.UTF8.
The C# code can handle 24 bytes keys (to support 3TDEA) and 16 bytes keys (to support the less secure 2TDEA). The posted CryptoJS code also handles these key sizes plus additionally 8 bytes keys (to support the least secure, DES compatible variant 1TDEA).
The following C# code decrypts a ciphertext generated with CryptoJS and 3TDEA:
public string Decrypt()
{
byte[] key = FromHexString("000102030405060708090a0b0c0d0e0f1011121314151617"); // 24 bytes (3TDEA)
byte[] iv = FromHexString("0001020304050607"); // 8 bytes
byte[] ciphertext = FromHexString("2116057c372e0e95dbe91fbfd148371b8e9974187b71e7c018de89c757280ad342d4191d29472040ee70d19015b025e1");
string plaintext = "";
using (TripleDES tdes = TripleDES.Create())
{
tdes.Key = key;
tdes.IV = iv;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, tdes.CreateDecryptor(tdes.Key, tdes.IV), CryptoStreamMode.Write))
{
cs.Write(ciphertext, 0, ciphertext.Length);
}
plaintext = Encoding.UTF8.GetString(ms.ToArray());
}
}
return plaintext;
}
The decryption is also possible with the posted JavaScript code, which shows the functional equivalence of both codes.
Note: Since AES is more performant than TripleDES, AES should be used if possible.
I have written a process where a file is encrypted and uploaded to Azure, then the download process has to be decrypted which is what fails with a "Padding is invalid and cannot be removed" error, or a "Length of the data to decrypt is invalid." error.
I've tried numerous solutions online, including C# Decrypting mp3 file using RijndaelManaged and CryptoStream, but none of them seem to work and I end up just bouncing back and forth between these two errors. The encryption process uses the same key/IV pair that decryption uses, and since it will decrypt a portion of the stream I feel like that's working fine - it just ends up dying with the above errors.
Here is my code, any ideas? Please note that the three variants (cryptoStream.CopyTo(decryptedStream), do {} and while) aren't run together - they are here to show the options I've already tried, all of which fail.
byte[] encryptedBytes = null;
using (var encryptedStream = new MemoryStream())
{
//download from Azure
cloudBlockBlob.DownloadToStream(encryptedStream);
//reset positioning for reading it back out
encryptedStream.Position = 0;
encryptedBytes = encryptedStream.ConvertToByteArray();
}
//used for the blob stream from Azure
using (var encryptedStream = new MemoryStream(encryptedBytes))
{
//stream where decrypted contents will be stored
using (var decryptedStream = new MemoryStream())
{
using (var aes = new RijndaelManaged { KeySize = 256, Key = blobKey.Key, IV = blobKey.IV })
{
using (var decryptor = aes.CreateDecryptor())
{
//decrypt stream and write it to parent stream
using (var cryptoStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read))
{
//fails here with "Length of the data to decrypt is invalid." error
cryptoStream.CopyTo(decryptedStream);
int data;
//fails here with "Length of the data to decrypt is invalid." error after it loops a number of times,
//implying it is in fact decrypting part of it, just not everything
do
{
data = cryptoStream.ReadByte();
decryptedStream.WriteByte((byte)cryptoStream.ReadByte());
} while (!cryptoStream.HasFlushedFinalBlock);
//fails here with "Length of the data to decrypt is invalid." error after it loops a number of times,
//implying it is in fact decrypting part of it, just not everything
while ((data = cryptoStream.ReadByte()) != -1)
{
decryptedStream.WriteByte((byte)data);
}
}
}
}
//reset position in prep for reading
decryptedStream.Position = 0;
return decryptedStream.ConvertToByteArray();
}
}
One of the comments mentioned wanting to know what ConvertToByteArray is, and it's just a simple extension method:
/// <summary>
/// Converts a Stream into a byte array.
/// </summary>
/// <param name="stream">The stream to convert.</param>
/// <returns>A byte[] array representing the current stream.</returns>
public static byte[] ConvertToByteArray(this Stream stream)
{
byte[] buffer = new byte[16 * 1024];
using (MemoryStream ms = new MemoryStream())
{
int read;
while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
{
ms.Write(buffer, 0, read);
}
return ms.ToArray();
}
}
The code never reaches this though - it dies before I can ever get it to this point.
After a lot of back and forth from various blogs, I found I actually had a couple of errors in the above code that were nailing me. First, the encryption process was incorrectly writing the array - it was wrapped with a CryptoStream instance, but wasn't actually utilizing that so I was writing the unencrypted data to Azure. Here is the proper route to go with this (fileKey is part of a custom class I created to generate Key/IV pairs, so wherever that is referenced can be changed to the built-in process from RijndaelManaged or anything else you'd utilize for coming up with a key/IV pair):
using (var aes = new RijndaelManaged { KeySize = 256, Key = fileKey.Key, IV = fileKey.IV })
{
using (var encryptedStream = new MemoryStream())
{
using (ICryptoTransform encryptor = aes.CreateEncryptor())
{
using (CryptoStream cryptoStream = new CryptoStream(encryptedStream, encryptor, CryptoStreamMode.Write))
{
using (var originalByteStream = new MemoryStream(file.File.Data))
{
int data;
while ((data = originalByteStream.ReadByte()) != -1)
cryptoStream.WriteByte((byte)data);
}
}
}
var encryptedBytes = encryptedStream.ToArray();
return encryptedBytes;
}
}
Second, since my encryption process involves multiple steps (three total keys per file - container, filename and file itself), when I tried to decrypt, I was using the wrong key (which is seen above when I referenced blobKey to decrypt, which was actually the key used for encrypting the filename and not the file itself. The proper decryption method was:
//used for the blob stream from Azure
using (var encryptedStream = new MemoryStream(encryptedBytes))
{
//stream where decrypted contents will be stored
using (var decryptedStream = new MemoryStream())
{
using (var aes = new RijndaelManaged { KeySize = 256, Key = blobKey.Key, IV = blobKey.IV })
{
using (var decryptor = aes.CreateDecryptor())
{
//decrypt stream and write it to parent stream
using (var cryptoStream = new CryptoStream(encryptedStream, decryptor, CryptoStreamMode.Read))
{
int data;
while ((data = cryptoStream.ReadByte()) != -1)
decryptedStream.WriteByte((byte)data);
}
}
}
//reset position in prep for reading
decryptedStream.Position = 0;
return decryptedStream.ConvertToByteArray();
}
}
I had looked into the Azure Encryption Extensions (http://www.stefangordon.com/introducing-azure-encryption-extensions/), but it was a little more local file-centric than I was interested - everything on my end is streams/in-memory only, and retrofitting that utility was going to be more work than it was worth.
Hopefully this helps anyone looking to encrypt Azure blobs with zero reliance on the underlying file system!
Bit late to the party, but in case this is useful to someone who finds this thread:
The following works well for me.
internal static byte[] AesEncryptor(byte[] key, byte[] iv, byte[] payload)
{
using (var aesAlg = Aes.Create())
{
aesAlg.Mode = CipherMode.CBC;
aesAlg.Padding = PaddingMode.PKCS7;
var encryptor = aesAlg.CreateEncryptor(key, iv);
var encrypted = encryptor.TransformFinalBlock(payload, 0, payload.Length);
return iv.Concat(encrypted).ToArray();
}
}
and to decrypt:
internal static byte[] AesDecryptor(byte[] key, byte[] iv, byte[] payload)
{
using (var aesAlg = Aes.Create())
{
aesAlg.Mode = CipherMode.CBC;
aesAlg.Padding = PaddingMode.PKCS7;
var decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
return decryptor.TransformFinalBlock(payload, 0, payload.Length);
}
}
this works for encrypting/decrypting both fixed length hex strings when decoded from hex to byte[] as well as utf8 variable length strings when decoded using Encoding.UTF8.GetBytes().
Im new to cryptography and im not quite sure what im doing wrong here,
public static byte[] EncryptData(byte[] data, string keystr)
{
if (keystr.Length > 32)
keystr = keystr.Substring(0, 32);
else
while (keystr.Length != 32)
keystr += "0";
byte[] iv = Encoding.UTF8.GetBytes(SALT);
byte[] key = Encoding.UTF8.GetBytes(keystr);
using (MemoryStream memoryStream = new MemoryStream())
{
using (RijndaelManaged rijndaelManaged = new RijndaelManaged { Key = key, IV = iv, Padding = PaddingMode.PKCS7, Mode = CipherMode.CBC })
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, rijndaelManaged.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
}
}
return memoryStream.ToArray();
}
}
public static byte[] DecryptData(byte[] data, string keystr)
{
if (keystr.Length > 32)
keystr = keystr.Substring(0, 32);
else
while (keystr.Length != 32)
keystr += "0";
byte[] iv = Encoding.UTF8.GetBytes(SALT);
byte[] key = Encoding.UTF8.GetBytes(keystr.ToUpper());
using (MemoryStream memoryStream = new MemoryStream())
{
using (RijndaelManaged rijndaelManaged = new RijndaelManaged { Key = key, IV = iv, Padding = PaddingMode.PKCS7, Mode = CipherMode.CBC })
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, rijndaelManaged.CreateDecryptor(key, iv), CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
}
}
return memoryStream.ToArray();
}
}
As you can see im passing in a byte array and a password. i make sure the password is always 32 chars.
Im getting Padding is invalid and cannot be removed. when i decrypt data.
The key and salt is always the same.
The key may be passed in the same to both methods, but for some reason, after you've thrown away more entropy (for longer strings) or padded out the key (for shorter strings), for some reason you do this:
keystr.ToUpper()
But only for the decryption side. So the keys being used are different.
I'd strongly suggest that you don't call ToUpper. Other suggestions would be to probably not have a fixed salt/IV and to allow both the iv and the key to be passed as byte arrays also, rather than strings. Encryption naturally deals with byte arrays, and putting wrapper methods like these in place that actually encourage weaker encryption is probably a bad idea.
I am facing with problem when decrypting data with usage of TripleDESCryptoServiceProvider. The problem is that decrypted value contains beside of original value some additional, strange characters at the end
Per instance if I provide "rastko" to be encrypted, I will get later with decryption something like this "rastko⥊㮶". For other values it could be different number of 'dummy' characters or in some cases I will get exact value.
Then, I saw that for all encrypted data byte array size is divisible by 8. It looks like any provided data is rounded on value that is divisible by 8. Only in case when original encoded value is divisible by 8, decryption will retrieve appropriate value.
Here are methods that I am using :
public static byte[] EncryptPassword(string password, out byte[] cryptoKey, out byte[] cryptoIV)
{
try
{
UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
byte[] unicodePassword = unicodeEncoding.GetBytes(password);
byte[] encryptedPassword;
using (TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider())
{
tripleDes.Key = GetCryptoKey();
tripleDes.Mode = CipherMode.CBC;
tripleDes.Padding = PaddingMode.PKCS7;
cryptoKey = tripleDes.Key;
cryptoIV = tripleDes.IV;
using (MemoryStream memoryStream = new MemoryStream())
{
ICryptoTransform cryptoTransform = tripleDes.CreateEncryptor();
using (
CryptoStream cryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
{
cryptoStream.Write(unicodePassword, 0, unicodePassword.Length);
////cryptoStream.FlushFinalBlock();
}
encryptedPassword = memoryStream.ToArray();
}
}
return encryptedPassword;
}
catch (Exception ex)
{
throw new Exception("Password encryption failed !", ex);
}
}
public static string DecryptPassword(byte[] encryptedPassword, byte[] cryptoKey, byte[] cryptoIV)
{
try
{
UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
string readablePassword;
using (TripleDESCryptoServiceProvider tripleDes = new TripleDESCryptoServiceProvider())
{
tripleDes.Key = cryptoKey;
tripleDes.IV = cryptoIV;
tripleDes.Mode = CipherMode.CBC;
tripleDes.Padding = PaddingMode.PKCS7;
// Create a new MemoryStream using the passed
// array of encrypted data.
using (MemoryStream memoryStream = new MemoryStream(encryptedPassword))
{
// Create crypto transform that defines the basic operations of cryptographic transformations.
ICryptoTransform cryptoTransform = tripleDes.CreateDecryptor();
// Create a CryptoStream using the MemoryStream and the passed key and initialization vector (IV).
using (CryptoStream decryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
{
decryptoStream.Write(encryptedPassword, 0, encryptedPassword.Length);
///decryptoStream.FlushFinalBlock();
}
byte[] decryptedPassword = memoryStream.ToArray();
//Convert the buffer into a string and return it.
readablePassword = unicodeEncoding.GetString(decryptedPassword, 0, decryptedPassword.Length);
}
}
return readablePassword;
}
catch (Exception ex)
{
throw new Exception("Password decryption failed !", ex);
}
}
private static byte[] GetCryptoKey()
{
UnicodeEncoding unicodeEncoding = new UnicodeEncoding();
string plainKey = "rastkoisajev2310982josipasenera153";
byte[] encodedKey = unicodeEncoding.GetBytes(plainKey);
// Prepares 192 bit key
byte[] preparedKey = new byte[24];
Array.Copy(encodedKey, preparedKey, 24);
return preparedKey;
}
Here is sample test invocation :
private static void CryptoTest()
{
string password = "rastko";
byte[] cryptoKey;
byte[] cryptoIV;
byte[] encryptedPassword = Crypto.EncryptPassword(password, out cryptoKey, out cryptoIV);
string decryptedPAssword = Crypto.DecryptPassword(encryptedPassword, cryptoKey, cryptoIV);
}
I have not good experience with security. What I see is that IV vector is 8byte size and as I found it is related to BlockSize, that is 8times greater then IV size. TripleDESCryptoServiceProvider for IV vector is using 8byte value. I can not change this.
Could you please tell me what I have to do or did I wrote something wrongly ?
DES is a 64 bit block cypher. Any text that does not divide cleanly into 64 bit (=8 byte) blocks needs to be padded to make up a whole number of blocks. You need to set padding for encryption and decryption. If you have control of both ends then use PKCS#5 padding to encrypt and decrypt. If you only have control over the decryption end, then ask the encrypting end what padding they are using and expect that.
Note that encrypting a password is normally not the way to go. Use PBKDF2 instead. Don't confuse passwords and keys!
Try to make sure that your CryptoStreams get closed or flushed:
http://msdn.microsoft.com/en-us/library/system.security.cryptography.cryptostream.flushfinalblock.aspx
If you don't then the padding/unpadding will likely not be performed, and you get trash instead.
After detail investigation I have found the solution for my problem.
I have changed a little bit decryption logic.
Instead of this part in DecryptPassword method :
// Create a CryptoStream using the MemoryStream and the passed key and initialization vector (IV).
using (CryptoStream decryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Write))
{
decryptoStream.Write(encryptedPassword, 0, encryptedPassword.Length);
///decryptoStream.FlushFinalBlock();
}
byte[] decryptedPassword = memoryStream.ToArray();
//Convert the buffer into a string and return it.
readablePassword = unicodeEncoding.GetString(decryptedPassword, 0, decryptedPassword.Length);
}
I am now using the Read logic from CryptoStream and then I am just removing nullable characters. It is like this now :
// Create a CryptoStream using the MemoryStream and the passed key and initialization vector (IV).
using (CryptoStream decryptoStream = new CryptoStream(memoryStream, cryptoTransform, CryptoStreamMode.Read))
{
// Create buffer to hold the decrypted data.
byte[] fromEncrypt = new byte[encryptedPassword.Length];
decryptoStream.Read(fromEncrypt, 0, fromEncrypt.Length);
//Convert the buffer into a string and return it.
readablePassword = unicodeEncoding.GetString(fromEncrypt);
readablePassword = readablePassword.Replace("\0", string.Empty);
}
This works perfectly for me ! Thank you all for your time.
I am trying to encrypt a stream (coming from a file) using AesManaged. I can encrypt the file without error, but on decryption I get the following CryptographicException:
Padding is invalid and cannot be
removed.
The exception is raised when the CryptoStream is being disposed. I use the following to encrypt the input data:
public byte[] Encrypt(Stream plain)
{
// Create a decrytor to perform the stream transform.
using( var msEncrypt = new MemoryStream() )
{
using (ICryptoTransform encryptor = _myAes.CreateEncryptor(_myAes.Key, _myAes.IV))
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
using (BinaryWriter swEncrypt = new BinaryWriter(csEncrypt))
{
int buf_size = 32768;
byte[] buffer = new byte[buf_size];
int read = 0;
while ((read = plain.Read(buffer, 0, buf_size)) > 0)
{
swEncrypt.Write(buffer, 0, read);
}
}
return msEncrypt.ToArray();
}
}
And this to decrypt the data:
public byte[] Decrypt(Stream cipherText)
{
using (MemoryStream ms = new MemoryStream())
{
// Create a decrytor to perform the stream transform.
using (ICryptoTransform decryptor = _myAes.CreateDecryptor(_myAes.Key, _myAes.IV))
using (CryptoStream csDecrypt = new CryptoStream(ms, decryptor, CryptoStreamMode.Write))
using (BinaryWriter swDecrypt = new BinaryWriter(csDecrypt))
{
int buf_size = 32768;
byte[] buffer = new byte[buf_size];
int read = 0;
while ((read = cipherText.Read(buffer, 0, buf_size)) > 0)
{
swDecrypt.Write(buffer, 0, read);
}
}
return ms.ToArray();
}
}
Any ideas about why this exception is coming up would be great. Thanks
UPDATE
Here is where the Aes object was created, note the Key and IV are just set to their current values temporarily, it is not the real key that will be used:
private Crypto()
{
_myAes = new AesManaged();
_myAes.Padding = PaddingMode.PKCS7;
_myAes.KeySize = 128;
_myAes.Key = Enumerable.Repeat((byte)'B', 128 / 8).ToArray();
_myAes.IV = Enumerable.Repeat((byte)'C', 128 / 8).ToArray();
}
In the past I got this exception when I tried to decrypt a buffer whose length was not a multiple of 16 bytes.
Did you try calling Flush on the CryptoStream before it is disposed? Possibly, if it isn't flushed then it ends up trying to decrypt a buffer with a non-aligned length.
And another note - I don't know if this will solve your problem, but when you create a CryptoStream in order to decrypt the buffer, shouldn't you be using CryptoStreamMode.Read instead of CryptoStreamMode.Write?
Ensure that you finish the CryptoStream cleanly on the write side. You may need to call FlushFinalBlock() to ensure that the end-of-stream padding is written through -- otherwise, you are likely to end up missing the final block of the stream, which will result in an invalid padding exception.
I don't know if it is still relevant to post something after 4 years but, you should try to set padding to none. I got the same problem with 3DES and the issue got solved with that (but make sure the length of data to be decrypted is correct...)
private Crypto()
{
_myAes = new AesManaged();
_myAes.Padding = PaddingMode.none; //rather than _myAes.Padding = PaddingMode.PKCS7;
_myAes.KeySize = 128;
_myAes.Key = Enumerable.Repeat((byte)'B', 128 / 8).ToArray();
_myAes.IV = Enumerable.Repeat((byte)'C', 128 / 8).ToArray();
}