I know there is plenty of this questions with answers around but I have spent hours and hours googleing and have tried all suggestions that I have found.
I download a file and I want to store it encrypted in the isolated storage.
This is how I store it:
using (var fs = new IsolatedStorageFileStream(fileName, FileMode.Create, store))
{
byte[] bytesInStream = new byte[args.Result.Length];
args.Result.Read(bytesInStream, 0, bytesInStream.Length);
var aes = new AesManaged
{
Key = GetBytes("aaaaaaaa"),
IV = GetBytes("bbbbbbbb")
};
byte[] encryptedArray;
using (MemoryStream memoryStream = new MemoryStream())
{
using (CryptoStream cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cryptoStream.Write(bytesInStream, 0, bytesInStream.Length);
cryptoStream.FlushFinalBlock();
encryptedArray = memoryStream.ToArray();
}
}
fs.Write(encryptedArray, 0, encryptedArray.Length);
fs.Flush();
}
The following code is for reading the file from isolated storage and decrypt it:
using (var store = IsolatedStorageFile.GetUserStoreForApplication())
{
if (store.FileExists(fileName))
{
var file = store.OpenFile(fileName, FileMode.Open,FileAccess.Read,FileShare.Read);
var reader = new BinaryReader(file);
var aes = new AesManaged
{
Key = GetBytes("aaaaaaaa"),
IV = GetBytes("bbbbbbbb")
};
byte[] decodedContent;
byte[] encodedContent = reader.ReadBytes(1280);
using (MemoryStream ms = new MemoryStream(encodedAudio))
{
using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Read))
{
BinaryReader r= new BinaryReader(cs);
decodedContent= r.ReadBytes(encodedContent.Length);
}
}
}
When the program reaches this line: decodedContent= r.ReadBytes(encodedContent.Length); I get CryptographicException with the following message: Padding is invalid and cannot be removed.
Can anyone help me with this issue?
You can't decrypt by blocks because silverlight AesManaged always include padding and if you read only a part of encrypted block - decryption class can't find the padding that should be removed. You can decrypt whole data only. Alternatively, you can split the data manually in the encryption part of your algorithm. Hans Passant told you the same, just in a short form ;)
You can decrypt 1,280 bytes at a time, if you decrypt without removing padding until the last block. That is, you have to set the decryptor to not remove padding (i.e. "no padding") on all but the last block.
I.e. when there are N blocks:
for blocks 1 to N-1: decrypt(1280 bytes, no padding)
for block N: decrypt(however many bytes left, padded)
You can also run the entire decryption with "no padding" and strip the padding yourself. The last byte will give you the number of bytes to clip from the end, from 1 to 16.
If you cannot turn off padding-removal on decryption (implied by your comment above), you can still decrypt 1,280 bytes at a time. Just encrypt the blocks individually. They will each get padding, and make it fit 1,280. For example, encrypt 1,279 bytes at a time (each block is given a 1 byte pad.) Encrypting the full 1,280 with padding will give you 1,296 bytes (a multiple of 16 bytes of plaintext is going to get a full 16-byte pad.)
Edit, for the interested:
If you find yourself with a large ciphertext, and you want to decrypt it in blocks, and for some reason your decryption is constrained such that you are forced to use padding mode PKCS#7, you can still decrypt the data a block at a time. It's a bit more expensive -- it will cost you an extra encryption of 16 bytes per block, but at least it is possible.
Take each block of raw ciphertext, and encrypt a little tail of 16 bytes for each block which is correctly padded for that block. Then decrypt the enlarged block, and finally, remove the extra bit of data used to encrypt the padding tail.
You just take the last 16 bytes of the block as your IV, and using the same key, encrypt some small data -- for example a single byte -- padded with PKCS#7. Attach the 16 byte result of the encryption to the block and now decrypt the block + 16 bytes. The padding is removed from the tail 16 bytes, and you can remove the bit of data, and end up with the original block of plaintext. See more in my answer here
Related
I have searched online but have not been able to find any solutions to my problem.
I am using previously written methods to encrypt and ecrypt text using the Rijndael class.
I use these functions to encrypt and decrypt usernames and emails for a web application I have been working on.
The encryption/decryption works perfectly, but every once in a while I get this error:
System.Security.Cryptography.CryptographicException: Length of the data to decrypt is invalid.
Currently, I am getting this error with a specific email address and I can't reproduce the error even if I replace some of the letters in the email.
Here are the encryption/decrytpion functions. The IV and Key are defined as read only strings.
static public string Encrypting(string Source)
{
byte[] bytIn = System.Text.ASCIIEncoding.ASCII.GetBytes(Source);
// create a MemoryStream so that the process can be done without I/O files
System.IO.MemoryStream ms = new System.IO.MemoryStream();
byte[] IVBytes = Encoding.ASCII.GetBytes(IV);
byte[] KEYBytes = Encoding.ASCII.GetBytes(KEY);
Rijndael rijndael = Rijndael.Create();
rijndael.IV = IVBytes;
rijndael.Key = KEYBytes;
// create Crypto Stream that transforms a stream using the encryption
CryptoStream cs = new CryptoStream(ms, rijndael.CreateEncryptor(), CryptoStreamMode.Write);
// write out encrypted content into MemoryStream
cs.Write(bytIn, 0, bytIn.Length);
cs.FlushFinalBlock();
// get the output and trim the '\0' bytes
byte[] bytOut = ms.GetBuffer();
int i = 0;
for (i = 0; i < bytOut.Length; i++)
if (bytOut[i] == 0)
break;
// convert into Base64 so that the result can be used in xml
return System.Convert.ToBase64String(bytOut, 0, i);
}
static public string Decrypting(string Source)
{
// convert from Base64 to binary
byte[] bytIn = System.Convert.FromBase64String(Source);
// create a MemoryStream with the input
System.IO.MemoryStream ms = new System.IO.MemoryStream(bytIn, 0, bytIn.Length);
byte[] IVBytes = Encoding.ASCII.GetBytes(IV);
byte[] KEYBytes = Encoding.ASCII.GetBytes(KEY);
Rijndael rijndael = Rijndael.Create();
rijndael.IV = IVBytes;
rijndael.Key = KEYBytes;
// create Crypto Stream that transforms a stream using the decryption
CryptoStream cs = new CryptoStream(ms, rijndael.CreateDecryptor(), CryptoStreamMode.Read);
// read out the result from the Crypto Stream
System.IO.StreamReader sr = new System.IO.StreamReader(cs);
return sr.ReadToEnd();
}
FYI - I am very new to cryptography and security.
Can these functions be fixed to avoid special cases that cause the error, or should I scrap these and use the RijndaelManaged class?
Sites I found that use RijndaelManaged:
SeeSharp
TekEye
The issue is almost certainly nothing to do with Rijndael vs. RijndaelManaged (or any other such implementation), but instead because the encrypted data contains a 0x00, and you are incorrectly assuming that the the ciphertext ends at the first 0x00 byte. Since the ciphertext can legitimately contain any byte value you should instead use the stream's Length property to determine the length of the ciphertext.
Eliminate the section you've commented: "get the output and trim the '\0' bytes" and replace the return ... statement with:
return System.Convert.ToBase64String(ms.GetBuffer(), 0, ms.Length);
It should be noted that there are many other issues with your use of cryptography here, e.g. the use of a key generated directly from the ASCII encoding of a string, and the fact you're using a fixed IV both negatively impact security.
The norm for the error is a padding issue. What version of .NET are you using? It is more common to use the AES classes (AES, or Advanced Encryption Standard, which is Rijndael). There are plenty of AES implementations you can find as samples.
If you need some proof AES is Rijndael: http://en.wikipedia.org/wiki/Advanced_Encryption_Standard
Suppose a small amount of data is being encrypted with AES using a 256 key / IV. The data encrypted could be known. For example:
abcdefghijklmno|axXXyyYY343433553353afsafaadfafdfsafsf|2013-01-01T00:00:00
The first two parts (if you break the data on the pipe character) rarely change. the last part, a date / time does change but not often. I've noticed that varying the date but not the first part of the message results in a cypher text which starts out the same all the time, presumably because the plain text is the same to start off.
Does this open me up to any kind of attacks against the encryption algorithm? Would I gain anything by prepending a salt value to the beginning of the plain text?
I'm using the AesManaged class to generate the IV / Key and encrypt / decrypt the plain text, if that makes a difference.
To solve this problem, normally the IV is generated randomly for each cypertext and prepended not encrypted to the encrypted data. In this way every encrypted data is different from the others.
In code it should be
string str = "abcdefghijklmno|axXXyyYY343433553353afsafaadfafdfsafsf|2013-01-01T00:00:00";
byte[] data = Encoding.UTF8.GetBytes(str);
byte[] key = new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; // Your random key, I hope more random!
byte[] encrypted;
// Encrypt
using (var am = new AesManaged())
using (var rng = new RNGCryptoServiceProvider())
{
am.Key = key;
var iv = new byte[am.BlockSize / 8];
rng.GetBytes(iv);
am.IV = iv;
using (var encryptor = am.CreateEncryptor())
using (var ms = new MemoryStream())
{
ms.Write(iv, 0, iv.Length);
using (var encStream = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
{
encStream.Write(data, 0, data.Length);
}
encrypted = ms.ToArray();
}
}
// Decrypt
string str2;
using (var am = new AesManaged())
using (var ms = new MemoryStream(encrypted))
{
am.Key = key;
var iv = new byte[am.BlockSize / 8];
ms.Read(iv, 0, iv.Length);
am.IV = iv;
using (var decryptor = am.CreateDecryptor())
using (var decStream = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
using (var ms2 = new MemoryStream())
{
decStream.CopyTo(ms2);
str2 = Encoding.UTF8.GetString(ms2.GetBuffer(), 0, (int)ms2.Length);
}
}
Note that in general IV reuse cause a weakness in encryption. See for example the wiki:
For CBC and CFB, reusing an IV leaks some information about the first block of plaintext, and about any common prefix shared by the two messages. For OFB and CTR, reusing an IV completely destroys security.[6]
This is one of the primary purposes of the IV. You should generate a random IV for each message that you send (if you're already doing that, something must be wrong in your code).
AES256 should mix data in blocks of 256 bits (32 bytes). Since you have a long leading text (>32 bytes) that rarely changes you will have poor performance using encryption method. You can fix this but beginning the plaintext string with something that changes frequently as long as it changes within the first 32 bytes. You can do this be creating some random seed and actual useful data.
The purpose of seeding is so that "known" strings will not generate recognizable patterns once encrypted. This is the exact problem you will have, so you need to seed you data or at least use volatile data near the beginning of your plaintext.
EDIT:
I saw I had a negatives and wondered why. First, by performance I was intending to refer to the quality of the encryption, not execution time. And I accidentally said seed when I meant salt. A minor mistakes, but I see why the negatives. I am leaving my answer because it is the only once that explains (or at attempts to explain) that the salt (or at least something) that changes frequently really needs to appear with the 32 bytes plaintext block fed to AES-256. Salting is usually required if your encrypted data is subject to dictionary attacks (such as passwords), which seem unlikely for the OP, but your encrypted data should never be "predictable", which is why the OP should salt with data within the first 32 bytes.
I use AES encryption. It's ok when I encrypt and then decrypt whole file. I want to add multiple files to one encrypted. That's where the problem is. Encryption is fine, but decryption causes CryptographicException - bad data length. Is it even possible to decrypt part of file or is it encrypted as whole ? I used one cryptostream and passed there all files I want to encrypt to single file. I am trying to do opposite:
AesManaged aes = AES.InitAes(key, salt);
ICryptoTransform transform = aes.CreateDecryptor(aes.Key, aes.IV);
int defChunkSize = 1024 * 1024 * 50;
using (FileStream source = new FileStream(header.data.filename, FileMode.Open))
{
foreach (CryptHeader.fileStruct file in header.data.files)
{
preparePath(file.filename);
using (FileStream target = new FileStream(file.filename, FileMode.Create))
{
using (CryptoStream cryptoStream = new CryptoStream(target, transform, CryptoStreamMode.Write))
{
long padding = source.Length - header.data.files.Sum(x => x.length);//Just test
int chunkSize = (defChunkSize > (int)file.length) ? (int)file.length : defChunkSize;
byte[] chunkData = new byte[chunkSize];
int bytesRead = 0;
int totalRead = 0;
while (totalRead < file.length)
{
bytesRead = source.Read(chunkData, 0, chunkSize);
if (bytesRead <= 0) break;
totalRead += bytesRead;
cryptoStream.Write(chunkData, 0, bytesRead);
}
chunkData = null;
}
}
}
}
I've done the same few years ago without any problem. The logic I used is the following:
Encryption
define number of files
define array for keeping encrypted sizes
open output stream
seek (forced) to (number of files * 4) + 4 (assuming lengths are integers)
loop for encryption (encrypt- write encrypted data -assigned encrypted size)
seek to 0 (begin)
write number of files
write encrypted size array
close output stream
Decryption
open input stream
read number of files
define-read-fill array with encrypted sizes
loop for decryption (read using known sizes)
close output stream
I hope that this helps.
Short form: "you can't get there from here", it's impossible.
If you look at the description of how AES works you'll see two things.
1 AES uses a block size of 128 bits, so if your files aren't multiples of 8 bytes in length the blocks in the appended part won't line up,
2: AES use uses different keys for each block according to the rijndael key schedule, this is a likely going to be a deal breaker.
If you need to be able to concatenate encrypted files either wrap them so that the joins are visible and the fragments can be individually decrypted (gzip does this when compressing) or use a fixed substitution cypher like rot13
It can be done and it's working. I make table during encryption containing lengths of encrypted files. Than I decrypt exact parts (with padding).
Mysql :
SELECT AES_ENCRYPT('Test','pass')
AES_ENCRYPT() and AES_DECRYPT() enable encryption and decryption of data using the official AES (Advanced Encryption Standard) algorithm, previously known as “Rijndael.” Encoding with a 128-bit key length is used, but you can extend it up to 256 bits by modifying the source. We chose 128 bits because it is much faster and it is secure enough for most purposes.
http://dev.mysql.com/doc/refman/5.5/en/encryption-functions.html#function_aes-encrypt
I was trying to convert that Encrypted string into Decryped Strig in C#.net but i don't get the results as i expect.
http://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndael.aspx#Y0
C#
static string DecryptStringFromBytes(byte[] cipherText, byte[] Key, byte[] IV)
In this method I pass ciphertext,Key value which i usedfrom Mysql and
Rijndael.Create().IV for byte[] IV
I use the code but i don't get expected result.
Review the code and comment Idk where made a mistake
What you are doing is following a road of pain. Either decrypt/encrypt on MySQL and use an encrypted connection to the database (if that matters) or encrypt/decrypt on your .NET application, storing the encrypted data in a suitable column.
Mixing AES implementations is prone to mistakes and things can break more easily if you change versions of .NET or MySQL.
Now, to know what exactly is wrong we need to know if the IV is compatible between MySQL and .NET, or else find out what is MySQL's implementation IV and supply that.
And the other potential source of problems is how you have generated the byte arrays (we are not seeing that in your example). You have to consider character encoding issues in generating the arrays if the key is textual.
In the comments of this MySQL docs link there is information about the missing parameters.
After a long hours, I found a solution to this issue.
Couple of FYI's:
MySQL as a default for AES_Encrypt uses 128 bit, with ECB mode, which does not require an IV.
What padding mode they use is not specified, but they do say they pad it. For padding I use PaddingMode.Zeros.
In C#, use AesManaged, not RijndaelManaged since that is not recommended anymore.
If your Key is longer than 128 bits (16 bytes), then use a function below to create the correct key size, since the default MySQL AES algorithm uses 128 bit keys.
Make sure you play around with the correct Encoding and know exactly what type of character encoding you will receive back when translating the bytes to characters.
For more info go here: https://forums.mysql.com/read.php?38,193084,195959#msg-195959
Code:
public static string DecryptAESStringFromBytes(byte[] encryptedText, byte[] key)
{
// Check arguments.
if ((encryptedText == null || encryptedText.Length <= 0) || (key == null || key.Length <= 0))
{
throw new ArgumentNullException("Missing arguments");
}
string decryptedText = null;
// Create an AES object with the specified key and IV.
using (AesManaged aesFactory = new AesManaged())
{
aesFactory.KeySize = 128;
aesFactory.Key = AESCreateKey(key, aesFactory.KeySize / 8);
aesFactory.IV = new byte[16];
aesFactory.BlockSize = 128;
aesFactory.Mode = CipherMode.ECB;
aesFactory.Padding = PaddingMode.Zeros;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aesFactory.CreateDecryptor();
// Create the streams used for decryption.
using (MemoryStream stream = new MemoryStream())
{
using (CryptoStream decryptStream = new CryptoStream(stream, decryptor, CryptoStreamMode.Write))
{
decryptStream.Write(encryptedText, 0, encryptedText.Length);
}
decryptedText = Encoding.Default.GetString(stream.ToArray());
}
}
return decryptedText.Trim();
}
public static byte[] AESCreateKey(byte[] key, int keyLength)
{
// Create the real key with the given key length.
byte[] realkey = new byte[keyLength];
// XOR each byte of the Key given with the real key until there's nothing left.
// This allows for keys longer than our Key Length and pads short keys to the required length.
for (int i = 0; i < key.Length; i++)
{
realkey[i % keyLength] ^= key[i];
}
return realkey;
}
Here is some working code for achieving the same encryption via C# as MySQL:
public byte[] AESEncrypt(byte[] plaintext, byte[] key) {
/*
* Block Length: 128bit
* Block Mode: ECB
* Data Padding: Padded by bytes which Asc() equal for number of padded bytes (done automagically)
* Key Padding: 0x00 padded to multiple of 16 bytes
* IV: None
*/
RijndaelManaged aes = new RijndaelManaged();
aes.BlockSize = 128;
aes.Mode = CipherMode.ECB;
aes.Key = key;
ICryptoTransform encryptor = aes.CreateEncryptor();
MemoryStream mem = new MemoryStream();
CryptoStream cryptStream = new CryptoStream(mem, encryptor,
CryptoStreamMode.Write);
cryptStream.Write(plaintext, 0, plaintext.Length);
cryptStream.FlushFinalBlock();
byte[] cypher = mem.ToArray();
cryptStream.Close();
cryptStream = null;
encryptor.Dispose();
aes = null;
return cypher;
}
For details see MySQL Bug # 16713
EDIT:
Since the above is relying on officially non-documented information (though it is working) I would recommend to avoid it and use one of the options described in the answer from Vinko Vrsalovic .
If you run SELECT AES_ENCRYPT('Test','pass')
your are sending the pass over the network unencrypted so any one can unencrypted the data.
The AES_ENCRYPT is used to store data so if the database gets hacked your data is safe, not to transmit data.
if you want data encryption over the net work connect to your mysql server using the ssl socket
I needed some simple string encryption, so I wrote the following code (with a great deal of "inspiration" from here):
// create and initialize a crypto algorithm
private static SymmetricAlgorithm getAlgorithm(string password) {
SymmetricAlgorithm algorithm = Rijndael.Create();
Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(
password, new byte[] {
0x53,0x6f,0x64,0x69,0x75,0x6d,0x20, // salty goodness
0x43,0x68,0x6c,0x6f,0x72,0x69,0x64,0x65
}
);
algorithm.Padding = PaddingMode.ISO10126;
algorithm.Key = rdb.GetBytes(32);
algorithm.IV = rdb.GetBytes(16);
return algorithm;
}
/*
* encryptString
* provides simple encryption of a string, with a given password
*/
public static string encryptString(string clearText, string password) {
SymmetricAlgorithm algorithm = getAlgorithm(password);
byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, algorithm.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(clearBytes, 0, clearBytes.Length);
cs.Close();
return Convert.ToBase64String(ms.ToArray());
}
/*
* decryptString
* provides simple decryption of a string, with a given password
*/
public static string decryptString(string cipherText, string password) {
SymmetricAlgorithm algorithm = getAlgorithm(password);
byte[] cipherBytes = Convert.FromBase64String(cipherText);
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, algorithm.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
return System.Text.Encoding.Unicode.GetString(ms.ToArray());
}
The code appears to work fine, except that when decrypting data with an incorrect key, I get a CryptographicException - "Padding is invalid and cannot be removed" - on the cs.Close() line in decryptString.
example code:
string password1 = "password";
string password2 = "letmein";
string startClearText = "The quick brown fox jumps over the lazy dog";
string cipherText = encryptString(startClearText, password1);
string endClearText = decryptString(cipherText, password2); // exception thrown
My question is, is this to be expected? I would have thought that decrypting with the wrong password would just result in nonsense output, rather than an exception.
Although this have been already answered I think it would be a good idea to explain why it is to be expected.
A padding scheme is usually applied because most cryptographic filters are not semantically secure and to prevent some forms of cryptoatacks. For example, usually in RSA the OAEP padding scheme is used which prevents some sorts of attacks (such as a chosen plaintext attack or blinding).
A padding scheme appends some (usually) random garbage to the message m before the message is sent. In the OAEP method, for example, two Oracles are used (this is a simplistic explanation):
Given the size of the modulus you padd k1 bits with 0 and k0 bits with a random number.
Then by applying some transformation to the message you obtain the padded message wich is encrypted and sent.
That provides you with a randomization for the messages and with a way to test if the message is garbage or not. As the padding scheme is reversible, when you decrypt the message whereas you can't say anything about the integrity of the message itself you can, in fact, make some assertion about the padding and thus you can know if the message has been correctly decrypted or you're doing something wrong (i.e someone has tampered with the message or you're using the wrong key)
I experienced a similar "Padding is invalid and cannot be removed." exception, but in my case the key IV and padding were correct.
It turned out that flushing the crypto stream is all that was missing.
Like this:
MemoryStream msr3 = new MemoryStream();
CryptoStream encStream = new CryptoStream(msr3, RijndaelAlg.CreateEncryptor(), CryptoStreamMode.Write);
encStream.Write(bar2, 0, bar2.Length);
// unless we flush the stream we would get "Padding is invalid and cannot be removed." exception when decoding
encStream.FlushFinalBlock();
byte[] bar3 = msr3.ToArray();
If you want your usage to be correct, you should add authentication to your ciphertext so that you can verify that it is the correct pasword or that the ciphertext hasn't been modified. The padding you are using ISO10126 will only throw an exception if the last byte doesn't decrypt as one of 16 valid values for padding (0x01-0x10). So you have a 1/16 chance of it NOT throwing the exception with the wrong password, where if you authenticate it you have a deterministic way to tell if your decryption is valid.
Using crypto api's while seemingly easy, actually is rather is easy to make mistakes. For example you use a fixed salt for for you key and iv derivation, that means every ciphertext encrypted with the same password will reuse it's IV with that key, that breaks semantic security with CBC mode, the IV needs to be both unpredictable and unique for a given key.
For that reason of easy to make mistakes, I have a code snippet, that I try to keep reviewed and up to date (comments, issues welcome):
Modern Examples of Symmetric Authenticated Encryption of a string C#.
If you use it's AESThenHMAC.AesSimpleDecryptWithPassword(ciphertext, password) when the wrong password is used, null is returned, if the ciphertext or iv has been modified post encryption null is returned, you will never get junk data back, or a padding exception.
If you've ruled out key-mismatch, then besides FlushFinalBlock() (see Yaniv's answer), calling Close() on the CryptoStream will also suffice.
If you are cleaning up resources strictly with using blocks, be sure to nest the block for the CryptoStream itself:
using (MemoryStream ms = new MemoryStream())
using (var enc = RijndaelAlg.CreateEncryptor())
{
using (CryptoStream encStream = new CryptoStream(ms, enc, CryptoStreamMode.Write))
{
encStream.Write(bar2, 0, bar2.Length);
} // implicit close
byte[] encArray = ms.ToArray();
}
I've been bitten by this (or similar):
using (MemoryStream ms = new MemoryStream())
using (var enc = RijndaelAlg.CreateEncryptor())
using (CryptoStream encStream = new CryptoStream(ms, enc, CryptoStreamMode.Write))
{
encStream.Write(bar2, 0, bar2.Length);
byte[] encArray = ms.ToArray();
} // implicit close -- too late!
Yes, this is to be expected, or at least, its exactly what happens when our crypto routines get non-decryptable data
Another reason of the exception might be a race condition between several threads using decryption logic - native implementations of ICryptoTransform are not thread-safe (e.g. SymmetricAlgorithm), so it should be put to exclusive section, e.g. using lock.
Please refer here for more details: http://www.make-awesome.com/2011/07/system-security-cryptography-and-thread-safety/
There may be some unread bytes in the CryptoStream. Closing before reading the stream completely was causing the error in my program.
I had a similar problem, the issue in decrypt method was initializing an empty memory stream. when it worked when I initialized it with the cipher text byte array like this:
MemoryStream ms = new MemoryStream(cipherText)
The answer updated by the user "atconway" worked for me.
The problem was not with the padding but the key which was different during encryption and decryption.
The key and iv should be same during encypting and decrypting the same value.