Keeping Private Keys Private

February 3, 2006

After I posted the CodeProject article .NET Encryption Simplified, a reader asked this question in the comments:

I would like to know what your thoughts are on private key storage in applications. I believe the recommended practice is to use the DPAPI, but I have found this to be too cumbersome for practical use. I would like to encrypt certain aspects of my apps and even parts of my database, but without secure key storage it is pointless. Thoughts?

The class in that article is suitable for most encryption scenarios, but I was using it in a web service. That meant I had the luxury of keeping my private key on a different physical server. I had never even considered the problem of private key storage on the same machine!

At the risk of belaboring the obvious, asymmetric encryption hinges on keeping the public key public, and the private key private. This is a snap if you're doing cross-machine calls. You slap the private key on your server, and freely distribute the public key to clients. The private key is never transmitted over the network, so unless a disgruntled user manages to battle his way into your data center and physically access your server, you're secure. But if all the encryption work you're doing is on the local machine, then the private key and the public key are both stored somewhere on the local machine. How in the world do you keep the private key away from the prying eyes of the local user?

It seems like an insoluble problem to me, since users have complete physical control over their own machines. However, a user named "bigals" posted this helpful response in the comments:

First of all, convert your private key to a PKCS12 file, which is a nice little container for private keys. Then you have a few options for storing the private key:

  1. In your machine's key store.
    This is not as safe as the user store, as it can be accessed by any user if they have enough permissions.
  2. In the current user's key store.
    This is more secure than the machine store, because it's protected by windows ACL's. But it can play havok on you if passwords and permissions are changed for that particular user.
  3. In the registry.
    You can use ACL's to protect the registry key.
  4. On a smart card.
    • The CryptoAPI has native support for this.
    • Smart cards can be removed and secured.
    • The keys are never stored on the machine, so it is a very secure solution.

Remember, never store an instance of your keys or passwords in a string! The .NET GC does not clear these values very well, and they are visible in the string table memory for anyone to steal! .NET 2.0 has a new object called SecureString, which keeps strings in encrypted memory.

This is another reason why the user comments are the best part of a blog. A two-way dialog between author and reader is often the difference between good content and great content.

The only way to keep a private key truly private is to store it on a completely different machine. If you must store the private key on the same machine, some vulnerability is inevitable. You can only make it inconvenient for a user to find the private key through software protection. If you want to make it really difficult, you have to embed the private key in specialized hardware, like the Xbox 360 does.

Posted by Jeff Atwood
7 Comments

And about shared enviroment? I'm thinking what the only solution is host my website myself... When we put the website in one ISP I simply cannot sleep at night, thinking WHERE I will store my private keys... I think what the Microsoft can think about this case when develop the next versions of .Net Framework...

Fabio on February 5, 2006 3:17 AM

But if my application can access the private key when it needs to then can't everyone's application access the private key?

Unfortunately, ACLs are your only option:

http://pluralsight.com/wiki/default.aspx/Keith.GuideBook/HowToStoreSecretsOnAMachine.html

Jeff Atwood on February 5, 2006 4:08 AM

http://www.xbox-linux.org/wiki/The_Hidden_Boot_Code_of_the_Xbox
--
But what happens if someone finds out the hidden 512 bytes? Bunnie (http://www.xenatera.com/bunnie/proj/anatak/xboxmod.html) did, Christmas 2001. He tapped the bus between the Southbridge (where the secret MCPX code is stored) and the Northbridge (the CPU's memory interface) where all secret data gets transmitted. The compromise to store the secret ROM in the MCPX instead of the CPU, so that data would travel over a bus, finally broke the system.
--

And that, in a nutshell, is why the PK is embedded in the CPU hardware on the Xbox 360.

You could remove the PK and store it on a remote server, but that would require the Xbox 360 to be connected to the internet to even boot up.. and I don't think the world is quite ready for a console that refuses to boot until it is connected to the internet.

It would still be theoretically possible to modify the client hardware to do a no-op when it should be authenticating. This might be extraordinarily difficult, though.

Jeff Atwood on February 5, 2006 5:52 AM

It seems to me that Windows should be able to provide us with an internal keystore that can only be accessed by signed assemblies from a specific company. In other words, I sign all of my assemblies with a certificate and then "install" my key using this same certificate. Any application that has not been signed with that same certificate is denied access to the installed key.

Does this type of functionality exist in Windows? If so, where? If not, why?

matt on February 5, 2006 10:26 AM

Very nice. But if my application can access the private key when it needs to then can't everyone's application access the private key? It seems like there needs to be an additional layer of protection there someone. How do we perform per-application (or even better, per-company) authentication before letting someone access the private keystore? Or is this what Windows is actually doing anyway?

Here is my other problem... I want to install and configure my program as an Adminstrator. But the user will "hopefully" be running my application as a Limited User. Doesn't this negate the benefits of protecting with ACL's?

matt on February 5, 2006 12:19 PM

Sounds like you want hardware-level guarantees of security for a given piece of software. This means you wall off data from other apps *and the user*.

Eg, Microsoft Palladium or NGSCB, which will be in Vista..

http://www.microsoft.com/technet/archive/security/news/ngscb.mspx

http://www.winsupersite.com/reviews/winvista_5270_03.asp

Jeff Atwood on February 6, 2006 1:23 AM

Jeff, that's exactly what I'm looking for. Thanks!

matt on February 6, 2006 9:33 AM

The comments to this entry are closed.