I was looking for a quick an easy way to generate a key pair that I could use to do some prototyping around encrypting data. I’m no crypto expert (or at least wasn’t!) and knew about SN.exe for signing .NET assemblies so I figured I’ll just use that. So I generated a key using the -k Foo.key command line option and then installed it into a machine container using sn -m y, sn -i Foo.key “FooKey”.
Next I hooked up a quick command line app that took some arbitrary data, loaded the key from the container using CspParameters::KeyContainerName into an RSACryptoServiceProvider and encrypted it and everything worked! I could encrypt and decrypt data and thought I was doing great.
Then I gave the same key to another developer and installed it the same way and he was able to encrypt and decrypt his own data just fine. The problems started when we begain trying to decrypt data that was encrpyted on each other’s machines. It just didn’t work. The key pair was the same, so why wasn’t it working?
Long story short, you can’t use SN to generate/install keys for encryption. It only creates/installs keys for signing. What I didn’t realize is that a key container of the same name can actually contain two types of keys: one for encryption and one for signing. The next thing I didn’t realize is that the .NET crypto implementation will generate a new key automatically if no key is found in the CspParameters::KeyContainerName specified. By default the implementations look for an encryption key and since I had only installed a signing key it was generating a new key in the container. That’s why my dev partner and I were unable to decrypt each other’s data cross machines… it was an entirely different, autogenerated key! I learned about all of this from this page which is ironically part of a site called JavaScience. 🙂
So what I did is use SnippetCompiler to generate a key pair and save it in XML format. Then I wrote a quick command line app takes the XML key pair and imports it into a named key container. It’s really weird that there’s no app provided with the SDK to do this. It turns out that they’ve actually built the functionality into the aspnet_regiis.exe utility in Whidbey (see the -p* prefixed options… for example, I needed the -px option).