How to Read Auto-Generated MachineKey

Posted on February 18, 2010  |  

Posted in Development

2 comments

Whether it's tamper-proofing ViewState, form authentication tickets, or generating session IDs, the <machineKey> section is behind it all. Even if you don't generate it by hand, there's one auto-generated for you.

My rule of thumb is to almost always generate one (using my own tool) because:

  1. I like to control the length of keys and the choice of algorithms.
  2. I often piggy-back off this section to use it as a Key/Initialization Vector pair for various cryptographic scenarios. You can see this approach in my open source project Shinkansen.

I could never understand why Microsoft didn't provide an easy way to read the auto-generated keys. I fired up my trusty Reflector and followed their code as far as I could, until I hit calls to The Unmanaged Side.

As you can tell from the screenshot below, both the DecryptionKey and ValidationKey are set to AutoGenerate,IsolateApps while DecryptionKeyInternal and ValidationKeyInternal contain perfectly valid, auto-generated keys. Except that they are marked internal.

Visual Studio Auto window with auto-generated machineKey section

With a little bit of reflection magic dust, it's easy enough to get to them:

protected void Page_Load (object sender, EventArgs e)
{
  MachineKeySection section = (MachineKeySection) 
      ConfigurationManager.GetSection ("system.web/machineKey");

  BindingFlags flags = 
      BindingFlags.Instance | 
      BindingFlags.NonPublic | 
      BindingFlags.GetProperty;

  Func<string, byte[]> propertyReader = name => (byte[]) section
      .GetType ()
      .GetProperty (name, flags)
      .GetValue (section, null);

  string key = ConvertToHex (
    propertyReader ("DecryptionKeyInternal"));
    
  string iv = ConvertToHex (
    propertyReader ("ValidationKeyInternal"));
}

private string ConvertToHex (byte[] binary)
{
  return binary.Aggregate (
      new StringBuilder (), 
      (acc, c) => acc.AppendFormat ("{0:x2}", c), 
      acc => acc.ToString());
}

Note: this code won't work in partial trust because of reflection. Still, I plan on using this technique to abstract away the difference between auto- and manually-generated keys.

I just wish they made this ordeal less complicated.

2 comments

arthur bw
on April 7, 2010

the tool used to generate a 3des machinekey and now that option does not appear to be available


Milan Negovan
on April 7, 2010

That's true. I've updated it in line with the latest best practices.