I totally agree. I need to rewrite this someday, in fact I had already answered such question (see below @ Steve44 / 8-Jun-13). Sorry if this article has caused you some confusion. I know that I had said (I'm quoting myself) "This will be the topic of a coming article" but the truth is that I barely have time for anything right now. Sorry about that!
Let me point out one problem with you usage of the IV: It is constant.
So when you encrypt the same file with the same key and IV, it will create the identical encrypted file, which is undesirable, as it tells an attacker that you sent/stored the identical file.
To mitigate this problem, a new IV should be generated for every encryption run. This way the encrypted file is different, even if you encrypt the same plaintext file.
As the IV is necessary for the successful decryption, it has to be kept with the encrypted file it belongs to. One possibility is to put the IV as a pre-fix to the encrypted file and the decryption then reads the first bytes, puts them in the IV and decrypts the remainder using the (secret) key and the embedded IV.
The RNGCryptoServiceProvider is a cryptography algorithm based pseudo-random generator, so it is "pretty random" or almost unpredictable. For anything truly random you would need to go to a HW-based solution that uses some physical phenomenon (e.g. thermal noise of a resistor or Zener-breakdown noise), however these solutions are limited as they can only produce a limited number or random values per second.
The other pseudo-random number generators (like Rnd or Rand) are much weaker than RNGCryptoServiceProvider due to the simplicity of their algorithms, but they are significantly faster if a huge amount of random numbers are required.
For the generation of the IV the randomness of the value is not as important as it is for other applications(e.g. generating a new key), the main property required here is "not reusing the same IV". For that reason I would not necessarily go to the RNGCryptoServiceProvider, but just call GenerateIV() on the AESCryptoServiceProvider (or whichever one you are using).
Let me know, if you have further questions.
Best regards, Steve
Fernando, Thank you for what you posted and I have a question about encryption in general and it relates to how you can remove all "DNA" of the encryption/decryption from memory once you've finished using it. I don't think that settings objects to null is the way to do it? What I'm getting at, is that if you leave an object containing the keys in memory there's no guarantee that setting it to null will force the GC to fully reclaim and destroy all resources still used. I read somewhere, that while it's unlikely to happen a smart person could get access to memory on a machine and see what private keys might still be there. For sure, it's really unlikely to happen but security auditors in some organisations would need guarantees that no keys are left "floating" around the objects. Do you have any thoughts on this?
I'm not trying to test you on anything as I genuinely would like to know what defensive measures you can adopt if you've come across anything?
If there is one thing more dangerous than getting between a bear and her cubs it's getting between my wife and her chocolate.
That's right. Setting it to null won't force the GC to reclaim the resources. You will need to take an array and manually set each byte to 0.
For example (being buffer = keyBytes or saltBytes or initVectorBytes):
publicstaticvoid ClearBytes(byte buffer)
// Check arguments.if (buffer == null)
// Set each byte in the buffer to 0.for (int x = 0; x < buffer.Length; x++)
buffer[x] = 0;
Yes it is, Rijndael is the standard version of AES. I don't know why VB Rocks, the original autor, treated them as separate items. In fact, the two methods do the same behind the scenes. This alternative version only adds C# code to an old implementation. In the days that follow I will code a personal solution that includes AES (Rijndael), TripleDES and RSA, with their respective providers, and the hashes needed, for encrypt/decrypt text and files. My knowledge of English is not as good as I want, but I will do my best to send you that solution, personally via Github or/and here on codeproject.
Yep acorrding to Wiki:
"AES is a variant of Rijndael which has a fixed block size of 128 bits, and a key size of 128, 192, or 256 bits."
Rijndael just states "block and key sizes that may be any multiple of 32 bits, both with a minimum of 128 and a maximum of 256 bits."
In 1997 NIST called for proposals for a new Advanced Encryption Standard (AES). In 2001, NIST declared the block cipher Rijndael as the new AES (in replacement of DSA) and published it as a final standard (FIPS PUB 197).
From that date to now, AES is the standard of the U.S. government for simmetryc cryptography, also known as Rijndael. It was presented to the AES Contest by two Belgian cryptologists, called Daemen and Rijmen, two students of the Catholic University of Leuven. This particular algorithm was selected over other fifteen finalists including Twofish, developed by Bruce Schneier.
There are big differences between each, but the official AES is Rijndael. This is so because the AES cipher is almost identical to the block cipher Rijndael. The Rijndael block and key size vary between 128, 192 and 256 bits. However, the AES standard only calls for a block size of 128 bits. Hence, only Rijndael with a block length of 128 bits is known as the AES algorithm.