г. Любопытно было любопытно получить ключ от машины. Свойства на MachineKeySection
не годятся, так как они обнуляются после инициализации , которая происходит до того, как вы сможете прочитать их с отражением.
После небольшого копания в текущей платформе 4.5 выясняется, что автоматически сгенерированные ключи хранятся в HttpApplication.s_autogenKeys
байтовом массиве. Ключ проверки - это первые 64 байта, за которыми следуют 24 байта ключа дешифрования.
Если вы не включили новые крипто-компоненты в 4.5 framework, то есть вы не установили <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);
Значением по умолчанию для обеих клавиш является AutoGenerate,IsolateApps
; бит IsolateApps
требует, чтобы вы скопировали первые четыре байта хэша пути приложения в начало ключа.
Если вы включили криптографические улучшения в fx4.5 , вам придется копаться в MachineKeyMasterKeyProvider , чтобы получить действительные ключи.
Получение ключей без HttpApplication
HttpApplication
получает свои ключи, вызывая собственный метод в webengine4.dll
из SetAutogenKeys()
. Мы можем сами вызвать 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()));
}
}
Получение ключей от MachineKeyMasterKeyProvider
Ключи для нового материала fx4.5 доступны путем создания экземпляра MachineKeyMasterKeyProvider
с внутренним конструктором , а затем передачи массива байтов autogenKeys
, полученного, как в коде выше. У провайдера есть методы GetEncryptionKey
и GetValidationKey
, чтобы получить действительные ключи.