I have a scenario that has been troubling me for years. If you have to connect to a database or other service (like a web service) using a username and password, where would be the safest place to store this information if you are connecting through a .NET assembly? I understand that you would have to encrypt the password, but then you run into a kind of chicken-egg problem -- fine -- you can encrypt it, but then where do you put the key?
In .NET, you can't hard-code the password because you can decompile .NET code.
I looked at using assembly based rights with Isolated Storage, but MS recommends against storing unencrypted secret items there because privileged users can gain access, so again, we are moving the problem from point A to point B. So, for example, a domain admin with no need to know about the information in a database would be able to get access because of the ability to be an admin on any workstation on the domain.
You can encrypt the App. Config and Web.Config, but I believe privileged users can access the keys.
I think you run into the same problem with DPAPI.
I had considered storing the passwords, encrypted in a remote database, and getting them through OS authentication, but our department prohibits the storage of passwords on database servers. I am pretty sure I am stuck and wanted confirmation.
You can use the following methods of the .NET Framework to protect your data; they use the DPAPI internally to protect your data, and you can directly use them in C# or VB.NET without having to fiddle around with system DLL calls:
To use it, add the reference
System.Security
to your project. I strongly recommend using the byte arrayoptionalEntropy
to add a SALT to your protected data (add some random values to the byte array which are unique for the data you intend to protect).For
scope
you can useDataProtectionScope.CurrentUser
, which will encrypt the data to protect with the current user's credentials.In some scenarios,
DataProtectionScope.LocalMachine
is useful, as well. In this case, the protected data is associated with the machine context. With this setting, any process running on the computer can unprotect data. It is usually used in server-specific applications that run on a server where untrusted users are not allowed access.Use the
Protect
method to encrypt the data, decrypt it withUnprotect
. You may store the returned byte array according to the requirements of your application (file, database, registry, etc).More about these methods can be found here at MSDN:
ProtectedData
class,Protect
methodFor code samples and in case you are interested in encrypting parts of the application's .config file, check this out:
I recommend you to use a SALT (by using the
optionalEntropy
parameter) - it protects against rainbow table attacks.There is one drawback of the DPAPI solution I'd like to mention: the key is generated based on your Windows credentials, which means whoever has access to your Windows credentials possibly has access to the protected data. A program running under your account can access the protected data as well.
This is good question and I've been looking for an answer myself. Problem I had was to keep db passwords secure in case server was hacked and individual files could be retrieved. One very interesting option I've found was that sections of web.config can be encrypted and decrypted automatically on the fly by .NET framework which would use Windows secure store to keep and retrieve encryption key for you. In my situation that was not available because my hosting provider was not supporting it but you may have a look at this option. Why I think it may work is that you can independently manage security of what users may access Windows secure store and significantly limit any potential breaches. A hacker who breaks into server might get a copy of your config files and all your assemblies but accessing decryption key would be another obstacle for him.
There are a couple of options here.
You don't want to store the password in the assembly, and reinventing the wheel only creates more trouble (and introduces more vulnerabilities) than it's worth. If you are using MS platform on both the database and web server, then the easiest way to handle this is use a trusted connection, and grant rights on the SQL server to the identity your application is using.
Second to that, I would just let DPAPI do its job to encrypt your connection settings.