获取当前的ASP.NET机器密钥

blo*_*art 16 asp.net machinekey

我发现自己想要获取当前应用程序的ASP.NET机器密钥.当然,如果在配置文件中指定了机器密钥,这很容易,但是如果它设置为自动生成,那么在任何地方似乎都没有公共方法来获取它.

基本上我想要它所以我可以为自己编写加密/ MACed cookie,就像ASP.NET Forms Authentication提供程序一样.

有没有人有任何指针或想法?

Mr.*_*ous 12

Curious先生对获得机器钥匙感到好奇.它们的属性MachineKeySection并不好,因为它们在初始化后会被清零,这可以在你用反射读取它们之前发生.

在对当前的4.5框架进行了一些挖掘后,结果发现自动生成的密钥存储在HttpApplication.s_autogenKeys字节数组中.验证密钥是前64个字节,后跟24个字节的解密密钥.

如果您没有选择加入4.5框架中的新加密内容,也就是说,您没有设置<httpRuntime targetFramework="4.5">在您的内容中web.config(如果您使用先前版本的框架创建了一个应用程序就是这种情况),那么您将进入像这样的键:

        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);
Run Code Online (Sandbox Code Playgroud)

两个键的默认值是AutoGenerate,IsolateApps; 该IsolateApps位要求您将应用程序路径哈希的前四个字节复制到密钥的开头.

如果您选择加入fx4.5中加密改进,那么您将不得不挖掘MachineKeyMasterKeyProvider来获取有效密钥.

在没有HttpApplication的情况下获取密钥

HttpApplication通过调用一个本地方法得到它的键webengine4.dllSetAutogenKeys().我们也可以自己调用DLL.我们需要知道的是我们的应用程序路径.

假设我们想要为根应用程序获取自动生成的密钥," /".

使用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()));
    }
}
Run Code Online (Sandbox Code Playgroud)

从MachineKeyMasterKeyProvider获取密钥

通过MachineKeyMasterKeyProvider使用内部构造函数实例化,然后传入autogenKeys上面代码中获得的字节数组,可以访问新fx4.5内容的键.提供者有方法GetEncryptionKeyGetValidationKey获得实际的密钥.


小智 5

如果你使用的是.NET 4,那就是MachineKey类.它不提供对实际密钥的原始访问,但它确实提供了使用与FormsAuthentication类相同的算法对数据进行编码和解码的方法,以及使用HMAC添加验证的选项.


小智 5

对于 .Net 4.5,这里是代码

//using System.Reflection
//using System.Web.Configuration

byte[] autogenKeys = (byte[])typeof(HttpRuntime).GetField("s_autogenKeys", BindingFlags.NonPublic | BindingFlags.Static).GetValue(null);

Type t = typeof(System.Web.Security.DefaultAuthenticationEventArgs).Assembly.GetType("System.Web.Security.Cryptography.MachineKeyMasterKeyProvider");
ConstructorInfo ctor = t.GetConstructors(BindingFlags.Instance | BindingFlags.NonPublic)[0];

Type ckey = typeof(System.Web.Security.DefaultAuthenticationEventArgs).Assembly.GetType("System.Web.Security.Cryptography.CryptographicKey");
ConstructorInfo ckeyCtor = ckey.GetConstructors(BindingFlags.Instance | BindingFlags.Public)[0];
Object ckeyobj = ckeyCtor.Invoke(new object[] { autogenKeys });
object o = ctor.Invoke(new object[] { new MachineKeySection(), null, null, ckeyobj, null });
var encKey = t.GetMethod("GetEncryptionKey").Invoke(o, null);
byte[] encBytes = ckey.GetMethod("GetKeyMaterial").Invoke(encKey, null) as byte[];
var vldKey = t.GetMethod("GetValidationKey").Invoke(o, null);
byte[] vldBytes = ckey.GetMethod("GetKeyMaterial").Invoke(vldKey, null) as byte[];
string decryptionKey = BitConverter.ToString(encBytes);
decryptionKey = decryptionKey.Replace("-", "");
string validationKey = BitConverter.ToString(vldBytes);
validationKey = validationKey.Replace("-", "");
Run Code Online (Sandbox Code Playgroud)


Tom*_*son 1

如果 ASP.NET 表单身份验证提供程序可以访问它,那么您是否尝试过查看提供程序源代码(我认为这是正确的位置,ScottGu关于该主题的原始博客文章自从更新 MSDN 以来就已经出现了损坏的链接)