Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting the current ASP.NET machine key

Tags:

I find myself wanting to get the ASP.NET machine key for the current application. This is, of course, easy if a machine key is specified in the configuration file, but if it's set to auto generate then there doesn't seem to be a public method anywhere to get it.

Basically I want at it so I can write an encrypted/MACed cookie for myself, just like the ASP.NET Forms Authentication provider does.

Does anyone have any pointers or ideas?

like image 928
blowdart Avatar asked Nov 18 '09 10:11

blowdart


People also ask

What is IIS machineKey?

The Machine Key is used to hash and/or encrypt cookies for the Alpha Anywhere Application Server for IIS. If multiple servers running IIS have different Machine Keys, the cookies created on one machine won't be usable on the other.

What is machineKey?

A machine key tightly secures gears, cams, sprockets, pulleys and other parts to the drive shaft in a power transmission and transmits torque from the main shaft to connected parts. A tapered machine key is used for easy assembly and removal.

What is machineKey validation?

Validation. Specifies the hashing algorithm that is used for validating forms authentication and view state data. ValidationAlgorithm. Gets or sets the name of the algorithm that is used to validate forms authentication and view state data. ValidationKey.


2 Answers

Mr. Curious was curious about getting the machine key as well. The properties on the MachineKeySection are no good, as they get zeroed-out after initialization, which happens before you can read them with reflection.

After a bit of digging in the current 4.5 framework, turns out that the auto generated keys are stored in HttpApplication.s_autogenKeys byte array. The validation key is the first 64 bytes, followed by 24 bytes of the decryption key.

If you are not opting in into the new crypto stuff in 4.5 framework, that is, you didn't set <httpRuntime targetFramework="4.5"> in your web.config (which is the case if you have an app you created with a previous version of the framework), then you get to the keys like this:

        byte[] autogenKeys = (byte[])typeof(HttpRuntime).GetField("s_autogenKeys", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);          int validationKeySize = 64;         int decryptionKeySize = 24;          byte[] validationKey = new byte[validationKeySize];         byte[] decryptionKey = new byte[decryptionKeySize];          Buffer.BlockCopy(autogenKeys, 0, validationKey, 0, validationKeySize);         Buffer.BlockCopy(autogenKeys, validationKeySize, decryptionKey, 0, decryptionKeySize);          // This is the IsolateApps bit, which is set for both keys         int pathHash = StringComparer.InvariantCultureIgnoreCase.GetHashCode(HttpRuntime.AppDomainAppVirtualPath);         validationKey[0] = (byte)(pathHash & 0xff);         validationKey[1] = (byte)((pathHash & 0xff00) >> 8);         validationKey[2] = (byte)((pathHash & 0xff0000) >> 16);         validationKey[3] = (byte)((pathHash & 0xff000000) >> 24);          decryptionKey[0] = (byte)(pathHash & 0xff);         decryptionKey[1] = (byte)((pathHash & 0xff00) >> 8);         decryptionKey[2] = (byte)((pathHash & 0xff0000) >> 16);         decryptionKey[3] = (byte)((pathHash & 0xff000000) >> 24); 

The default for both keys is AutoGenerate,IsolateApps; the IsolateApps bit requires that you copy the first four bytes of the application path hash to the beginning of the key.

If you opted in into the cryptographic improvements in fx4.5, then you'll have to dig around the MachineKeyMasterKeyProvider to get the valid keys.

Getting the Keys without the HttpApplication

The HttpApplication gets its keys by calling into a native method in webengine4.dll from SetAutogenKeys(). We can call into the DLL ourselves as well. All we need to know is our application path.

Let's say that we want to get the auto generated keys for the root application, "/".

Using LinqPad:

[DllImport(@"C:\Windows\Microsoft.NET\Framework\v4.0.30319\webengine4.dll")] internal static extern int EcbCallISAPI(IntPtr pECB, int iFunction, byte[] bufferIn, int sizeIn, byte[] bufferOut, int sizeOut);  void Main() {     string appPath = "/";     byte[] genKeys = new byte[1024];     byte[] autogenKeys = new byte[1024];      int res = EcbCallISAPI(IntPtr.Zero, 4, genKeys, genKeys.Length, autogenKeys, autogenKeys.Length);      if (res == 1) {         // Same as above         int validationKeySize = 64;         int decryptionKeySize = 24;          byte[] validationKey = new byte[validationKeySize];         byte[] decryptionKey = new byte[decryptionKeySize];          Buffer.BlockCopy(autogenKeys, 0, validationKey, 0, validationKeySize);         Buffer.BlockCopy(autogenKeys, validationKeySize, decryptionKey, 0, decryptionKeySize);          int pathHash = StringComparer.InvariantCultureIgnoreCase.GetHashCode(appPath);         validationKey[0] = (byte)(pathHash & 0xff);         validationKey[1] = (byte)((pathHash & 0xff00) >> 8);         validationKey[2] = (byte)((pathHash & 0xff0000) >> 16);         validationKey[3] = (byte)((pathHash & 0xff000000) >> 24);          decryptionKey[0] = (byte)(pathHash & 0xff);         decryptionKey[1] = (byte)((pathHash & 0xff00) >> 8);         decryptionKey[2] = (byte)((pathHash & 0xff0000) >> 16);         decryptionKey[3] = (byte)((pathHash & 0xff000000) >> 24);          Console.WriteLine("DecryptionKey: {0}", decryptionKey.Aggregate(new StringBuilder(), (acc, c) => acc.AppendFormat("{0:x2}", c), acc => acc.ToString()));         Console.WriteLine("ValidationKey: {0}", validationKey.Aggregate(new StringBuilder(), (acc, c) => acc.AppendFormat("{0:x2}", c), acc => acc.ToString()));     } } 

Getting the keys from MachineKeyMasterKeyProvider

The keys for the new fx4.5 stuff are accessible by instantiating the MachineKeyMasterKeyProvider with the internal constructor, and then passing in autogenKeys byte array obtained as in the code above. The provider has methods GetEncryptionKey and GetValidationKey to get to actual keys.

like image 138
Mr. Curious Avatar answered Sep 20 '22 12:09

Mr. Curious


If you're using .NET 4, there's the MachineKey class. It doesn't give you raw access to the actual key, but it does provide methods for Encoding and Decoding the data using the same algorithms as the FormsAuthentication class, along with options for adding validation w/ an HMAC.

like image 23
Paul Avatar answered Sep 21 '22 12:09

Paul