When generating a symmetric key to encrypt a message, you create a byte array in your process’s memory.
Next you instantiate a SymmetricAlgorithm such as AesCryptoServiceProvider. Then typically you set the key property to your in-memory key.
You then create an ICryptoTransform, typically by calling SymmetricAlgorithm.CreateEncryptor() or CreateDecryptor(). You can also skip setting the Key property above and pass the key and IV directly to CreateEncryptor(byte[], byte[]) or CreateDecryptor(byte[], byte[]).
-
Is it safer to zero the byte array as soon as the ICryptoTransform is created to prevent rogue software reading it? While the byte array is in use generating cryptographic random data and initializing the transform, does pinning provide any security?
-
If you set the SymmetricAlgorithm.Key property, is there an additional copy somewhere or just a pointer back to your secret byte array? Is it safer to dispose the SymmetricAlgorithm immediately after creating the transform?
-
When the ICryptoTransform is created, I’m assuming there is an additional copy now in the RAM. So for the duration of the life of the ICryptoTransform object, is the key readable by rogue software? How about after disposal?
In other words if I have a stream to which my software intermittently writes encrypted data, is it better to encrypt each little bit with a separate key and destroy/dispose everything I can in between to minimize the time during which the key could be stolen?
Someone may say that once there is rogue software on a computer, nothing is safe, therefore it’s useless to worry about it. I’d still rather take steps to minimize potential damage caused by an attacker gaining access to encryption keys for personal data.
No, it’s no safer.
It doesn’t matter, and no, it’s no safer.
Yes, it is readable by any software with the privileges to do so. After disposal it probably can’t be read, since Dispose() in .Net crypto generally zeros the memory.
There have been many religious arguments about this, however I’ll just make the answer as clear as possible from a practical sense: if ‘rogue software’, ie malware, is running with the privileges to access the memory space of your decryption program, it can not only read the keys, but the data that you decrypt. Surely that’s more of an issue – since that’s what the key protects, after all. You’re not going to stop the user from viewing their own data, are you? So then you’re not adding any security.
To put it another way, the tennets of computability are supplementing, not replacing, the rules of security on the host platform. The two add together, and both are needed for security. Without host security on the decrypting machine, you can’t have cryptographic security. Attempts to add it just add more complexity and increase the likelihood that you’ll introduce a real bug (although .NET does your memory management for you, so that’s less of an issue here).