DevDays: Deploying Application Secrets
One question that I didn't have time to address during the OpenHack talk is how the encrypted encryption key, the entropy for the DPAPI calls and the connection string to access the Awards database are encrypted and stored in the registry.
I mentioned that each if these items is encrypted using DPAPI, but didn't really mention when and how that's done.
If you take a look at the Visual Studio solution in the OpenHack directory on the DevDays DVD, then you will find two projects. The OpenHack web site and another project called Tools. This project builds a command line executable that runs during the installation of the OpenHack web site. It uses the the same classes to make DPAPI available to managed code as the OpenHack web application itself.
When you run the tool, it will call the managed code wrappers for the DPAPI ProtectData method to encrypt data and then store it in the registry keys for the application to read.
The tool also creates the application specific entropy value used with DPAPI data protection by getting a 32 byte long sequence of random bytes using the RNGCryptoServiceProvider class from the .NET Framework:
RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider();
byte[] entropy = new byte[32];
rng.GetBytes(entropy);
Then it stores that value in the registry, calls DPAPI's ProtectData function to encrypt the connection string and stores both, the entropy and the encrypted string in the registry. The entropy value is a way to customize the machine specific DPAPI encryption key to a specific application. Remember, DPAPI's machine specific encryption key would be the same for each application running on the machine. Adding an application specific entropy value allows only applications that have access to the entropy value to decrypt DPAPI protected data.
With the entropy and the encrypted connection string in the registry, the OpenHack application can get the information to access the database.
The installer tool then proceeds to create a symmetric key for the data that is stored in the database.
byte[] desKey = null;
byte[] iv = null;
SymmetricAlgorithm alg = TripleDES.Create();
desKey = alg.Key;
iv = new byte[ alg.BlockSize / 8 ];
rng.GetBytes(iv);
This is where the OpenHack developers took a short cut because they knew that the application would only run on one web server, i.e. only one server would ever require the encryption key. In applications with more than one web server, you would have to come up with a different strategy because you need to get the same key to all web servers - you can't just have the installer create a different key on every machine as it was done in OpenHack. Each web server needs the same key or your application could only access data that was encrypted on a particular web server.
Because protecting your encryption key is really a key element to your security effort (pun intended) you have be very cautious about how you deploy the encryption key to the web server, and of course where you keep it between the deployments. Your encrypted data is only as secure as your encryption key. If someone gets your key, they can decrypt your sensitive data. If every developer and IT person in your organization has access to your encryption key -- because its in a .msi file on your build server for example -- then every developer and every IT person is a threat to the security of your data. Storing keys in a safe location and being cautious about deploying them is much more an organization problem than a technological problem. Chapter 9 in "Writing Secure Code 2nd edition" (the big silver book you got in the PDC backpack) provides some additional information.
Regardless on how you decide to keep your encryption key safe, deploying the secrets separately from the application, as done in OpenHack is a good step to take to allowing access to the secrets only to the people that need them.