Best Way to Store Encryption Keys in .Net C#

Best way to store encryption keys in .NET C#

If you want to protect your data from other users. Take a look at the ProtectedData class.

(Disclaimer: Protecting your data to create a copy protection scheme is not covered in this answer).

This classes uses the DPAPI from Windows, to encrypt and decrypt data on user or machine level.

Using ProtectedData/DPAPI frees you from handling keys and securing the data yourself. And you can choose to protect the data for the current user. The data can be read from different computers, by the same domain users.

If you want create your own key. You can create a key per user/machine, and store this key in the registry. Because the registry can be secured, only the current user can read the key back. I know the registry has bad karma, but is actually very good at storing data like this.

PS: Do not put the IV in your code. Create a new IV every time, and put it in front of the data.

Proper way to store encryption keys for use with multiple apps across multiple machines

Have you considered using the Transparent Data Encryption feature of SQL Server?

While it's not a key storage mechanism per se, if your goal is to protect the data "at rest" (i.e. in the database files on the filesystem and in all backups), then this may provide a way to do that without having your own encryption method split between the various applications.

TDE is not the most complicated thing to set up, but make sure you understand how the certificates and keys are used, and that you know what you need to back-up (and store securely) to be able to recover data and restore backups to different machines and the like.

It won't fix your distributed key issue, but you could either do away with the requirement to encrypt/decrypt the data into and out of the database in each application and have the database do it transparently.

As another alternative, you could also use a separate TDE-secured database on the central server as the store for your encryption key, which all the other applications can then access.

With TDE, you're correct in that anyone with credentials to the SQL Server would be able to access the data in plain-text, so you'd need to protect the credentials to the server, as you mentioned.

Protecting Credentials

As you have machines spread between different operating systems and domains, you probably need multiple different ways of protecting the credentials on each one (which I guess you know).

For Windows machines on the same domain as the SQL Server (or a domain trusted by the SQL Server), you can't really beat a Group Managed Service Account. They are a domain-level account that cannot be interactively logged in, have a very long and periodically mutating password, and can only be used by service accounts. With these, you don't need SQL account credentials because you can grant database permissions directly to the service account (the connection string uses "Integrated_Security=True").

For Windows machines not on the domain, a sensible way to store credentials is with the Data Protection API. With this, you can give the SQL Username and Password credentials to your code (running as some low-priviledge service user), which it then DPAPI protects and stores in a file. That way, only code running as that service user would be able to read them back out. Nefarious code accessing the filesystem from another user wouldn't be able to decrypt them.

As for Linux, that's not really my area, sorry.

Certificates

To throw even more food for thought in, all operating systems (well, at least Windows and Linux) have some way of protecting certificates and their private keys, and many frameworks (such as .NET) have methods for using certificates to encrypt and decrypt data. You could potentially generate a certificate and private key (which gives you an Asymmetric key pair), and install them both on each on your servers.

With that, you can then generate a Symmetric key (for 3DES or AES, for example), then encrypt the Symmetric key with your certificate's Asymmetric public key. The encrypted Symmetric key can be put in a central database or somewhere else. Only applications with the asymmetric private key to decrypt the symmetric key would then be able to use it to decrypt the data.

How to safely store encryption key in a .NET assembly

You have to decide what is an acceptable level of risk. There is no "safe" way of doing this.

If the risk of someone using reflector, or just opening up the assembly using the System.Reflection.Assembly class and grabbing the resource that way, is too great, then your next step is probably to download the key from the server when you start up.

Then someone will have to do something like debug while using your code and grab the key that way. You can expire stuff that is cached and swap out the keys. You can make it so that individuals each have their own keys to protect one user's data from another user.

You can do a lot of stuff but if your goal is to keep someone from being able to decrypt information that an assembly you are putting on their machine has the ability to decrypt, you should know it's pretty much impossible. All you can really do is elevate the cost of pirating your keys/data; you can't stop it.

Securing encryption keys in C#

You don't. If the application can access the key, it is just security by obscurity. It is better to authenticate the user in some way (a password is the simplest example), to make sure he is allowed to access the data. You can't let the application do that for you, because it simply isn't trustworthy. Anyone can obtain the information stored in the application.

If the key information is stored somewhere else, a malicious user or application can probably access it, too. If not, then store your data directly to that magical safe place.

Now if you still want to go down that path and store sensitive data without authentication, your best bet - or at least an easy way that is halfway secure - is probably the DPAPI (see the ProtectedData class in System.Security.Cryptography). It will encrypt the data either with the machine key or to the user account key (you can select that). So that a program running on another machine or with another user account can't access it. Windows will try to protect those keys but in effect any application running on the proper machine or with the proper user account may be able to access your data.

What to use for a encryption key and where to store?

Personally I would store the key in the configuration file for the application.
Either the app.config file, or the web.config file (depending on whether its a desktop or web app).

<add key="EncryptionKey" value="MY_KEY" />

I would generate the key using some random string generator.

Do you anticipate having to change the key often?

Also -- for the production transformation of your web.config, I would recommend leaving the encryption key out of your SCM solution (GIT, SVN, etc). I keep all of ours in a separate KeyPass database.

Encryption and Decryption Key, where to store and what to use for .net application

An secure asymmetric encryption algorithm is what you need. Such an algorithm has two keys: A public key, that can be used to encrypt, but not decrypt, and a private key, which can be used to decrypt.

Choose an algorithm, making sure to research its characteristics (RSA is the common choice in .NET I think); generate a private/public key pair, store the private key somewhere on the internal site where it cannot be accessed from outside, and put the public key somewhere both the internal and the external site can find it.

Storing encryption keys in asp.net application

"Security" can only be defined against a certain threat.

Most encryption based security is protecting against someone eavesdropping on your communication.

If I was an attacker who somehow gained access to the web server, ...

That is a much more severe threat. A common protection against it is the double firewall:

Your WebServer (IIS #1) serves the public but has no access to the database. It hast to call an Application Server (IIS #2) behind the second firewall.

The aspx page would use the same set of apis to query the database (i.e. XyzRepository.GetAll() kind of calls)

When the API has a call like that, the data is not considered secret.



Related Topics



Leave a reply



Submit