Code:
/ Net / Net / 3.5.50727.3053 / DEVDIV / depot / DevDiv / releases / whidbey / netfxsp / ndp / fx / src / xsp / System / Web / Configuration / MachineKeySection.cs / 6 / MachineKeySection.cs
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
namespace System.Web.Configuration
{
using System;
using System.Xml;
using System.Configuration;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System.Web.Util;
using System.Globalization;
using System.Web.Hosting;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Security.Permissions;
/*
*/
[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
public sealed class MachineKeySection : ConfigurationSection
{
private static ConfigurationPropertyCollection _properties;
private static readonly ConfigurationProperty _propValidationKey =
new ConfigurationProperty("validationKey", typeof(string), "AutoGenerate,IsolateApps", StdValidatorsAndConverters.WhiteSpaceTrimStringConverter, StdValidatorsAndConverters.NonEmptyStringValidator, ConfigurationPropertyOptions.None);
private static readonly ConfigurationProperty _propDecryptionKey =
new ConfigurationProperty("decryptionKey", typeof(string),"AutoGenerate,IsolateApps",StdValidatorsAndConverters.WhiteSpaceTrimStringConverter, StdValidatorsAndConverters.NonEmptyStringValidator, ConfigurationPropertyOptions.None);
private static readonly ConfigurationProperty _propDecryption =
new ConfigurationProperty("decryption", typeof(string), "Auto", StdValidatorsAndConverters.WhiteSpaceTrimStringConverter, StdValidatorsAndConverters.NonEmptyStringValidator, ConfigurationPropertyOptions.None);
private static readonly ConfigurationProperty _propValidation =
new ConfigurationProperty("validation", typeof(MachineKeyValidation), MachineKeyValidation.SHA1, new MachineKeyValidationConverter(), null, ConfigurationPropertyOptions.None);
private static readonly ConfigurationProperty _propCompatibilityMode =
new ConfigurationProperty("compatibilityMode", typeof(MachineKeyCompatibilityMode), MachineKeyCompatibilityMode.Framework20SP1, null, null, ConfigurationPropertyOptions.None);
private const int HASH_SIZE = 20;
private const int BLOCK_SIZE = 64;
static object s_initLock = new object();
static MachineKeySection s_config;
static MachineKeyCompatibilityMode s_compatMode;
private static RNGCryptoServiceProvider s_randomNumberGenerator;
private static SymmetricAlgorithm s_oSymAlgoDecryption;
private static Stack s_oEncryptorStackDecryption;
private static Stack s_oDecryptorStackDecryption;
private static SymmetricAlgorithm s_oSymAlgoValidation;
private static Stack s_oEncryptorStackValidation;
private static Stack s_oDecryptorStackValidation;
private static byte[] s_validationKey;
private static byte[] s_inner = null;
private static byte[] s_outer = null;
internal static bool IsDecryptionKeyAutogenerated { get { EnsureConfig(); return s_config.AutogenKey; } }
private bool _AutogenKey;
internal bool AutogenKey { get { RuntimeDataInitialize(); return _AutogenKey; } }
private byte[] _ValidationKey;
private byte[] _DecryptionKey;
private bool DataInitialized = false;
internal byte[] ValidationKeyInternal { get { RuntimeDataInitialize(); return (byte[])_ValidationKey.Clone(); } }
internal byte[] DecryptionKeyInternal { get { RuntimeDataInitialize(); return (byte[])_DecryptionKey.Clone(); } }
#if UNUSED
static internal int ValidationKeyHashCode
{
get
{
EnsureConfig();
return ByteArrayToHexString(s_validationKey, s_validationKey.Length).GetHashCode();
}
}
#endif
static MachineKeySection()
{
// Property initialization
_properties = new ConfigurationPropertyCollection();
_properties.Add(_propValidationKey);
_properties.Add(_propDecryptionKey);
_properties.Add(_propValidation);
_properties.Add(_propDecryption);
_properties.Add(_propCompatibilityMode);
}
public MachineKeySection()
{
}
internal static MachineKeyCompatibilityMode CompatMode
{
get
{
EnsureConfig();
return s_compatMode;
}
}
protected override ConfigurationPropertyCollection Properties
{
get
{
return _properties;
}
}
[ConfigurationProperty("validationKey", DefaultValue = "AutoGenerate,IsolateApps")]
[TypeConverter(typeof(WhiteSpaceTrimStringConverter))]
[StringValidator(MinLength = 1)]
public string ValidationKey
{
get
{
return (string)base[_propValidationKey];
}
set
{
base[_propValidationKey] = value;
}
}
[ConfigurationProperty("decryptionKey", DefaultValue = "AutoGenerate,IsolateApps")]
[TypeConverter(typeof(WhiteSpaceTrimStringConverter))]
[StringValidator(MinLength = 1)]
public string DecryptionKey
{
get
{
return (string)base[_propDecryptionKey];
}
set
{
base[_propDecryptionKey] = value;
}
}
[ConfigurationProperty("decryption", DefaultValue = "Auto")]
[TypeConverter(typeof(WhiteSpaceTrimStringConverter))]
[StringValidator(MinLength = 1)]
public string Decryption {
get {
string s = base[_propDecryption] as string;
if (s == null)
return "Auto";
if (s != "Auto" && s != "AES" && s != "3DES" && s != "DES")
throw new ConfigurationErrorsException(SR.GetString(SR.Wrong_decryption_enum), ElementInformation.Properties["decryption"].Source, ElementInformation.Properties["decryption"].LineNumber);
return s;
}
set {
if (value != "AES" && value != "3DES" && value != "Auto" && value != "DES")
throw new ConfigurationErrorsException(SR.GetString(SR.Wrong_decryption_enum), ElementInformation.Properties["decryption"].Source, ElementInformation.Properties["decryption"].LineNumber);
base[_propDecryption] = value;
}
}
private bool _validationIsCached;
private MachineKeyValidation _cachedValidation;
[ConfigurationProperty("validation", DefaultValue = MachineKeyValidation.SHA1)]
[TypeConverter(typeof(MachineKeyValidationConverter ))]
public MachineKeyValidation Validation
{
get
{
if (_validationIsCached == false) {
_cachedValidation = (MachineKeyValidation)base[_propValidation];
_validationIsCached = true;
}
return _cachedValidation;
}
set
{
base[_propValidation] = value;
_cachedValidation = value;
_validationIsCached = true;
}
}
[ConfigurationProperty("compatibilityMode", DefaultValue = MachineKeyCompatibilityMode.Framework20SP1)]
public MachineKeyCompatibilityMode CompatibilityMode
{
get
{
return (MachineKeyCompatibilityMode)base[_propCompatibilityMode];
}
set
{
base[_propCompatibilityMode] = value;
}
}
protected override void Reset(ConfigurationElement parentElement)
{
MachineKeySection parent = parentElement as MachineKeySection;
base.Reset(parentElement);
// copy the privates from the parent.
if (parent != null)
{
// _ValidationKey = parent.ValidationKeyInternal;
// _DecryptionKey = parent.DecryptionKeyInternal;
// _AutogenKey = parent.AutogenKey;
}
}
private void RuntimeDataInitialize()
{
if (DataInitialized == false)
{
byte [] bKeysRandom = null;
bool fNonHttpApp = false;
string strKey = ValidationKey;
string appName = HttpRuntime.AppDomainAppVirtualPath;
if( appName == null )
{
#if !FEATURE_PAL // FEATURE_PAL does not enable cryptography
// FEATURE_PAL
appName = System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName;
if( ValidationKey.Contains( "AutoGenerate" ) ||
DecryptionKey.Contains( "AutoGenerate" ) )
{
fNonHttpApp = true;
bKeysRandom = new byte[ BLOCK_SIZE + 24 ];
RNGCryptoServiceProvider randgen = new RNGCryptoServiceProvider();
// Gernerate random keys
randgen.GetBytes( bKeysRandom );
}
#endif // !FEATURE_PAL
}
bool fAppSpecific = StringUtil.StringEndsWith(strKey, ",IsolateApps");
if (fAppSpecific)
{
strKey = strKey.Substring(0, strKey.Length - ",IsolateApps".Length);
}
if (strKey == "AutoGenerate")
{ // case sensitive
_ValidationKey = new byte[BLOCK_SIZE];
if( fNonHttpApp )
{
Buffer.BlockCopy( bKeysRandom, 0, _ValidationKey, 0, BLOCK_SIZE);
}
else
{
Buffer.BlockCopy(HttpRuntime.s_autogenKeys, 0, _ValidationKey, 0, BLOCK_SIZE);
}
}
else
{
if (strKey.Length > 128 || strKey.Length < 40)
throw new ConfigurationErrorsException(SR.GetString(SR.Unable_to_get_cookie_authentication_validation_key, strKey.Length.ToString(CultureInfo.InvariantCulture)), ElementInformation.Properties["validationKey"].Source, ElementInformation.Properties["validationKey"].LineNumber);
_ValidationKey = HexStringToByteArray(strKey);
if (_ValidationKey == null)
throw new ConfigurationErrorsException(SR.GetString(SR.Invalid_validation_key), ElementInformation.Properties["validationKey"].Source, ElementInformation.Properties["validationKey"].LineNumber);
}
if (fAppSpecific)
{
int dwCode = StringComparer.InvariantCultureIgnoreCase.GetHashCode( appName );
_ValidationKey[0] = (byte)(dwCode & 0xff);
_ValidationKey[1] = (byte)((dwCode & 0xff00) >> 8);
_ValidationKey[2] = (byte)((dwCode & 0xff0000) >> 16);
_ValidationKey[3] = (byte)((dwCode & 0xff000000) >> 24);
}
strKey = DecryptionKey;
fAppSpecific = StringUtil.StringEndsWith(strKey, ",IsolateApps");
if (fAppSpecific)
{
strKey = strKey.Substring(0, strKey.Length - ",IsolateApps".Length);
}
if (strKey == "AutoGenerate")
{ // case sensitive
_DecryptionKey = new byte[24];
if( fNonHttpApp )
{
Buffer.BlockCopy( bKeysRandom, BLOCK_SIZE, _DecryptionKey, 0, 24);
}
else
{
Buffer.BlockCopy(HttpRuntime.s_autogenKeys, BLOCK_SIZE, _DecryptionKey, 0, 24);
}
_AutogenKey = true;
}
else
{
_AutogenKey = false;
if ((strKey.Length % 2) != 0)
throw new ConfigurationErrorsException(SR.GetString(SR.Invalid_decryption_key), ElementInformation.Properties["decryptionKey"].Source, ElementInformation.Properties["decryptionKey"].LineNumber);
_DecryptionKey = HexStringToByteArray(strKey);
if (_DecryptionKey == null)
throw new ConfigurationErrorsException(SR.GetString(SR.Invalid_decryption_key), ElementInformation.Properties["decryptionKey"].Source, ElementInformation.Properties["decryptionKey"].LineNumber);
}
if (fAppSpecific)
{
int dwCode = StringComparer.InvariantCultureIgnoreCase.GetHashCode(appName);
_DecryptionKey[0] = (byte)(dwCode & 0xff);
_DecryptionKey[1] = (byte)((dwCode & 0xff00) >> 8);
_DecryptionKey[2] = (byte)((dwCode & 0xff0000) >> 16);
_DecryptionKey[3] = (byte)((dwCode & 0xff000000) >> 24);
}
DataInitialized = true;
}
}
internal static byte[] EncryptOrDecryptData(bool fEncrypt, byte[] buf, byte[] modifier, int start, int length)
{
// DevDiv Bugs 137864: IVType.Hash is the default for compatibility reasons. It allows the result to be
// consistent across multiple calls with the same data. This was the behavior when there was no padding.
return EncryptOrDecryptData(fEncrypt, buf, modifier, start, length, IVType.Hash, false);
}
internal static byte[] EncryptOrDecryptData(bool fEncrypt, byte[] buf, byte[] modifier, int start, int length, bool useValidationSymAlgo)
{
// DevDiv Bugs 137864: IVType.Hash is the default for compatibility reasons. It allows the result to be
// consistent across multiple calls with the same data. This was the behavior when there was no padding.
return EncryptOrDecryptData(fEncrypt, buf, modifier, start, length, IVType.Hash, useValidationSymAlgo);
}
internal static byte[] EncryptOrDecryptData(bool fEncrypt, byte[] buf, byte[] modifier, int start, int length, IVType ivType)
{
return EncryptOrDecryptData(fEncrypt, buf, modifier, start, length, ivType, false);
}
internal static byte[] EncryptOrDecryptData(bool fEncrypt, byte[] buf, byte[] modifier, int start, int length, IVType ivType, bool useValidationSymAlgo)
{
EnsureConfig();
System.IO.MemoryStream ms = new System.IO.MemoryStream();
ICryptoTransform oDesEnc = GetCryptoTransform(fEncrypt, useValidationSymAlgo);
CryptoStream cs = new CryptoStream(ms, oDesEnc, CryptoStreamMode.Write);
// DevDiv Bugs 137864: Add Random or Hashed IV to beginning of data to be encrypted.
// IVType.None is used by MembershipProvider which requires compatibility even in SP2 mode.
bool createIV = ((ivType != IVType.None) && (CompatMode > MachineKeyCompatibilityMode.Framework20SP1));
if (fEncrypt && createIV)
{
byte[] iv = null;
switch (ivType)
{
case IVType.Hash:
iv = GetIVHash(buf, useValidationSymAlgo);
break;
case IVType.Random:
iv = GetIVRandom(useValidationSymAlgo);
break;
}
Debug.Assert(iv != null, "Invalid value for IVType: " + ivType.ToString("G"));
cs.Write(iv, 0, iv.Length);
}
cs.Write(buf, start, length);
if (fEncrypt && modifier != null)
{
cs.Write(modifier, 0, modifier.Length);
}
cs.FlushFinalBlock();
byte[] paddedData = ms.ToArray();
byte[] bData;
cs.Close();
ReturnCryptoTransform(fEncrypt, oDesEnc, useValidationSymAlgo);
// DevDiv Bugs 137864: Strip Random or Hashed IV from beginning of unencrypted data
if (!fEncrypt && createIV)
{
// strip off the first bytes that were either random bits or a hash of the original data
// either way it is always equal to the key length
int ivLength = GetIVLength(useValidationSymAlgo);
int bDataLength = paddedData.Length - ivLength;
// valid if the data is long enough to have included the padding
if (bDataLength >= 0)
{
bData = new byte[bDataLength];
// copy from the padded data to non-padded buffer bData.
// dont bother with copy if the data is entirely the padding
if (bDataLength > 0)
{
Buffer.BlockCopy(paddedData, ivLength, bData, 0, bDataLength);
}
}
else
{
// data is not padded because it is not long enough
bData = paddedData;
}
}
else
{
bData = paddedData;
}
if (!fEncrypt && modifier != null && modifier.Length > 0)
{
for(int iter=0; iter= s_validationKey.Length) {
// Buffer.BlockCopy(s_validationKey, 0, buf, start + length, s_validationKey.Length);
// byte[] computedHash = md5.ComputeHash(buf, start, length + s_validationKey.Length);
//
// // Cleanup validation key from buf
// for (int i = (start + length); i < (start + length + s_validationKey.Length); i++) {
// buf[i] = 0;
// }
//
// return computedHash;
// }
// }
byte[] bAll = new byte[totalLength];
Buffer.BlockCopy(buf, start, bAll, 0, length);
if (modifier != null)
{
Buffer.BlockCopy(modifier, 0, bAll, length, modifier.Length);
length += modifier.Length;
}
Buffer.BlockCopy(s_validationKey, 0, bAll, length, s_validationKey.Length);
return md5.ComputeHash(bAll);
}
private static void SetInnerOuterKeys(byte[] validationKey) {
byte[] key = null;
if (validationKey.Length > BLOCK_SIZE) {
key = new byte[HASH_SIZE];
int hr = UnsafeNativeMethods.GetSHA1Hash(validationKey, validationKey.Length, key, key.Length);
Marshal.ThrowExceptionForHR(hr);
}
if (s_inner == null)
s_inner = new byte[BLOCK_SIZE];
if (s_outer == null)
s_outer = new byte[BLOCK_SIZE];
int i;
for (i=0; i < BLOCK_SIZE; i++) {
s_inner[i] = 0x36;
s_outer[i] = 0x5C;
}
for (i=0; i < validationKey.Length; i++) {
s_inner[i] ^= validationKey[i];
s_outer[i] ^= validationKey[i];
}
}
private static byte[] GetHMACSHA1Hash(byte[] buf, byte[] modifier, int start, int length) {
if (length < 0 || buf == null || length > buf.Length)
throw new ArgumentException(SR.GetString(SR.InvalidArgumentValue, "length"));
if (start < 0 || start >= length)
throw new ArgumentException(SR.GetString(SR.InvalidArgumentValue, "start"));
byte[] buffer = new byte[HASH_SIZE];
int hr = UnsafeNativeMethods.GetHMACSHA1Hash(buf, start, length,
modifier, (modifier == null) ? 0 : modifier.Length,
s_inner, s_inner.Length, s_outer, s_outer.Length,
buffer, buffer.Length);
Marshal.ThrowExceptionForHR(hr);
return buffer;
}
internal static string HashAndBase64EncodeString(string s)
{
byte[] ab;
byte[] hash;
string result;
ab = Encoding.Unicode.GetBytes(s);
hash = HashData(ab, null, 0, ab.Length);
result = Convert.ToBase64String(hash);
return result;
}
static internal void DestroyByteArray(byte[] buf)
{
if (buf == null || buf.Length < 1)
return;
for (int iter = 0; iter < buf.Length; iter++)
buf[iter] = (byte)0;
}
internal void DestroyKeys()
{
MachineKeySection.DestroyByteArray(_ValidationKey);
MachineKeySection.DestroyByteArray(_DecryptionKey);
}
static char[] s_acharval;
static unsafe internal String ByteArrayToHexString(byte[] buf, int iLen)
{
char[] acharval = s_acharval;
if (acharval == null)
{
acharval = new char[16];
for (int i = acharval.Length; --i >= 0; )
{
if (i < 10)
{
acharval[i] = (char)('0' + i);
}
else
{
acharval[i] = (char)('A' + (i - 10));
}
}
s_acharval = acharval;
}
if (buf == null)
return null;
if (iLen == 0)
iLen = buf.Length;
char[] chars = new char[iLen * 2];
fixed (char* fc = chars, fcharval = acharval)
{
fixed (byte* fb = buf)
{
char* pc;
byte* pb;
pc = fc;
pb = fb;
while (--iLen >= 0)
{
*pc++ = fcharval[(*pb & 0xf0) >> 4];
*pc++ = fcharval[*pb & 0x0f];
pb++;
}
}
}
return new String(chars);
}
static void EnsureConfig()
{
if (s_config == null)
{
lock (s_initLock)
{
if (s_config == null)
{
MachineKeySection config = RuntimeConfig.GetAppConfig().MachineKey;
config.ConfigureEncryptionObject();
s_config = config;
s_compatMode = config.CompatibilityMode;
}
}
}
}
// NOTE: When encoding the data, this method *may* return the same reference to the input "buf" parameter
// with the hash appended in the end if there's enough space. The "length" parameter would also be
// appropriately adjusted in those cases. This is an optimization to prevent unnecessary copying of
// buffers.
internal static byte[] GetEncodedData(byte[] buf, byte[] modifier, int start, ref int length)
{
EnsureConfig();
byte[] bHash = HashData(buf, modifier, start, length);
byte[] returnBuffer;
if (buf.Length - start - length >= bHash.Length)
{
// Append hash to end of buffer if there's space
Buffer.BlockCopy(bHash, 0, buf, start + length, bHash.Length);
returnBuffer = buf;
}
else
{
returnBuffer = new byte[length + bHash.Length];
Buffer.BlockCopy(buf, start, returnBuffer, 0, length);
Buffer.BlockCopy(bHash, 0, returnBuffer, length, bHash.Length);
start = 0;
}
length += bHash.Length;
if (s_config.Validation == MachineKeyValidation.TripleDES || s_config.Validation == MachineKeyValidation.AES) {
returnBuffer = EncryptOrDecryptData(true, returnBuffer, modifier, start, length, true);
length = returnBuffer.Length;
}
return returnBuffer;
}
// NOTE: When decoding the data, this method *may* return the same reference to the input "buf" parameter
// with the "dataLength" parameter containing the actual length of the data in the "buf" (i.e. length of actual
// data is (total length of data - hash length)). This is an optimization to prevent unnecessary copying of buffers.
internal static byte[] GetDecodedData(byte[] buf, byte[] modifier, int start, int length, ref int dataLength)
{
EnsureConfig();
if (s_config.Validation == MachineKeyValidation.TripleDES || s_config.Validation == MachineKeyValidation.AES) {
buf = EncryptOrDecryptData(false, buf, modifier, start, length, true);
if (buf == null || buf.Length < HASH_SIZE)
throw new HttpException(SR.GetString(SR.Unable_to_validate_data));
length = buf.Length;
start = 0;
}
if (length < HASH_SIZE || start < 0 || start >= length)
throw new HttpException(SR.GetString(SR.Unable_to_validate_data));
byte[] bHash = HashData(buf, modifier, start, length - HASH_SIZE);
for (int iter = 0; iter < bHash.Length; iter++)
if (bHash[iter] != buf[start + length - HASH_SIZE + iter])
throw new HttpException(SR.GetString(SR.Unable_to_validate_data));
dataLength = length - HASH_SIZE;
return buf;
}
internal static byte[] HashData(byte[] buf, byte[] modifier, int start, int length)
{
EnsureConfig();
byte[] hash = null;
if (s_config.Validation == MachineKeyValidation.MD5)
hash = MD5HashForData(buf, modifier, start, length);
else
hash = GetHMACSHA1Hash(buf, modifier, start, length);
// We need to pad the returning hash so that they all have an uniform size (makes it easier when we decode)
// MD5 will return a 16 byte hash, whereas the default SHA1 returns 20, so we pad it with 4 zero bytes
System.Web.Util.Debug.Assert(hash.Length <= HASH_SIZE, "Hash size is greater than HASH_SIZE constant!");
if (hash.Length < HASH_SIZE)
{
byte[] tmp = new byte[HASH_SIZE];
Buffer.BlockCopy(hash, 0, tmp, 0, hash.Length);
hash = tmp;
}
return hash;
}
private void ConfigureEncryptionObject()
{
using (new ApplicationImpersonationContext()) {
s_validationKey = ValidationKeyInternal;
byte[] dKey = DecryptionKeyInternal;
SetInnerOuterKeys(s_validationKey);
DestroyKeys();
switch (Decryption) {
case "3DES":
s_oSymAlgoDecryption = new TripleDESCryptoServiceProvider();
break;
case "DES":
s_oSymAlgoDecryption = new DESCryptoServiceProvider();
break;
case "AES":
s_oSymAlgoDecryption = new RijndaelManaged();
break;
default: // "Auto" case
if (dKey.Length == 8) {
s_oSymAlgoDecryption = new DESCryptoServiceProvider();
} else {
s_oSymAlgoDecryption = new RijndaelManaged();
}
break;
}
switch(Validation)
{
case MachineKeyValidation.TripleDES:
if (dKey.Length == 8) {
s_oSymAlgoValidation = new DESCryptoServiceProvider();
} else {
s_oSymAlgoValidation = new TripleDESCryptoServiceProvider();
}
break;
case MachineKeyValidation.AES:
s_oSymAlgoValidation = new RijndaelManaged();
break;
}
if (s_oSymAlgoValidation != null) {
SetKeyOnSymAlgorithm(s_oSymAlgoValidation, dKey);
s_oEncryptorStackValidation = new Stack();
s_oDecryptorStackValidation = new Stack();
}
SetKeyOnSymAlgorithm(s_oSymAlgoDecryption, dKey);
s_oEncryptorStackDecryption = new Stack();
s_oDecryptorStackDecryption = new Stack();
DestroyByteArray(dKey);
}
}
private void SetKeyOnSymAlgorithm(SymmetricAlgorithm symAlgo, byte[] dKey)
{
try {
if (dKey.Length == 24 && symAlgo is DESCryptoServiceProvider) {
byte[] bTemp = new byte[8];
Buffer.BlockCopy(dKey, 0, bTemp, 0, 8);
symAlgo.Key = bTemp;
DestroyByteArray(bTemp);
} else {
symAlgo.Key = dKey;
}
symAlgo.GenerateIV();
symAlgo.IV = new byte[symAlgo.IV.Length];
} catch (Exception e) {
throw new ConfigurationErrorsException(SR.GetString(SR.Bad_machine_key, e.Message), ElementInformation.Properties["decryptionKey"].Source, ElementInformation.Properties["decryptionKey"].LineNumber);
}
}
private static ICryptoTransform GetCryptoTransform(bool fEncrypt, bool useValidationSymAlgo)
{
Stack st;
if (useValidationSymAlgo) {
st = (fEncrypt ? s_oEncryptorStackValidation : s_oDecryptorStackValidation);
} else {
st = (fEncrypt ? s_oEncryptorStackDecryption : s_oDecryptorStackDecryption);
}
lock (st) {
if (st.Count > 0)
return (ICryptoTransform)st.Pop();
}
if (useValidationSymAlgo) {
lock (s_oSymAlgoValidation) {
return (fEncrypt ? s_oSymAlgoValidation.CreateEncryptor() : s_oSymAlgoValidation.CreateDecryptor());
}
} else {
lock (s_oSymAlgoDecryption) {
return (fEncrypt ? s_oSymAlgoDecryption.CreateEncryptor() : s_oSymAlgoDecryption.CreateDecryptor());
}
}
}
private static void ReturnCryptoTransform(bool fEncrypt, ICryptoTransform ct, bool useValidationSymAlgo)
{
Stack st;
if (useValidationSymAlgo) {
st = (fEncrypt ? s_oEncryptorStackValidation : s_oDecryptorStackValidation);
} else {
st = (fEncrypt ? s_oEncryptorStackDecryption : s_oDecryptorStackDecryption);
}
lock (st) {
if (st.Count <= 100)
st.Push(ct);
}
}
static byte[] s_ahexval;
static internal byte[] HexStringToByteArray(String str)
{
if (((uint)str.Length & 0x1) == 0x1) // must be 2 nibbles per byte
{
return null;
}
byte[] ahexval = s_ahexval; // initialize a table for faster lookups
if (ahexval == null)
{
ahexval = new byte['f' + 1];
for (int i = ahexval.Length; --i >= 0; )
{
if ('0' <= i && i <= '9')
{
ahexval[i] = (byte)(i - '0');
}
else if ('a' <= i && i <= 'f')
{
ahexval[i] = (byte)(i - 'a' + 10);
}
else if ('A' <= i && i <= 'F')
{
ahexval[i] = (byte)(i - 'A' + 10);
}
}
s_ahexval = ahexval;
}
byte[] result = new byte[str.Length / 2];
int istr = 0, ir = 0;
int n = result.Length;
while (--n >= 0)
{
int c1, c2;
try
{
c1 = ahexval[str[istr++]];
}
catch (ArgumentNullException)
{
c1 = 0;
return null;// Inavlid char
}
catch (ArgumentException)
{
c1 = 0;
return null;// Inavlid char
}
catch (IndexOutOfRangeException)
{
c1 = 0;
return null;// Inavlid char
}
try
{
c2 = ahexval[str[istr++]];
}
catch (ArgumentNullException)
{
c2 = 0;
return null;// Inavlid char
}
catch (ArgumentException)
{
c2 = 0;
return null;// Inavlid char
}
catch (IndexOutOfRangeException)
{
c2 = 0;
return null;// Inavlid char
}
result[ir++] = (byte)((c1 << 4) + c2);
}
return result;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//-----------------------------------------------------------------------------
namespace System.Web.Configuration
{
using System;
using System.Xml;
using System.Configuration;
using System.Collections.Specialized;
using System.Collections;
using System.IO;
using System.Text;
using System.Security.Cryptography;
using System.Web.Util;
using System.Globalization;
using System.Web.Hosting;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Security.Permissions;
/*
*/
[AspNetHostingPermission(SecurityAction.LinkDemand, Level=AspNetHostingPermissionLevel.Minimal)]
public sealed class MachineKeySection : ConfigurationSection
{
private static ConfigurationPropertyCollection _properties;
private static readonly ConfigurationProperty _propValidationKey =
new ConfigurationProperty("validationKey", typeof(string), "AutoGenerate,IsolateApps", StdValidatorsAndConverters.WhiteSpaceTrimStringConverter, StdValidatorsAndConverters.NonEmptyStringValidator, ConfigurationPropertyOptions.None);
private static readonly ConfigurationProperty _propDecryptionKey =
new ConfigurationProperty("decryptionKey", typeof(string),"AutoGenerate,IsolateApps",StdValidatorsAndConverters.WhiteSpaceTrimStringConverter, StdValidatorsAndConverters.NonEmptyStringValidator, ConfigurationPropertyOptions.None);
private static readonly ConfigurationProperty _propDecryption =
new ConfigurationProperty("decryption", typeof(string), "Auto", StdValidatorsAndConverters.WhiteSpaceTrimStringConverter, StdValidatorsAndConverters.NonEmptyStringValidator, ConfigurationPropertyOptions.None);
private static readonly ConfigurationProperty _propValidation =
new ConfigurationProperty("validation", typeof(MachineKeyValidation), MachineKeyValidation.SHA1, new MachineKeyValidationConverter(), null, ConfigurationPropertyOptions.None);
private static readonly ConfigurationProperty _propCompatibilityMode =
new ConfigurationProperty("compatibilityMode", typeof(MachineKeyCompatibilityMode), MachineKeyCompatibilityMode.Framework20SP1, null, null, ConfigurationPropertyOptions.None);
private const int HASH_SIZE = 20;
private const int BLOCK_SIZE = 64;
static object s_initLock = new object();
static MachineKeySection s_config;
static MachineKeyCompatibilityMode s_compatMode;
private static RNGCryptoServiceProvider s_randomNumberGenerator;
private static SymmetricAlgorithm s_oSymAlgoDecryption;
private static Stack s_oEncryptorStackDecryption;
private static Stack s_oDecryptorStackDecryption;
private static SymmetricAlgorithm s_oSymAlgoValidation;
private static Stack s_oEncryptorStackValidation;
private static Stack s_oDecryptorStackValidation;
private static byte[] s_validationKey;
private static byte[] s_inner = null;
private static byte[] s_outer = null;
internal static bool IsDecryptionKeyAutogenerated { get { EnsureConfig(); return s_config.AutogenKey; } }
private bool _AutogenKey;
internal bool AutogenKey { get { RuntimeDataInitialize(); return _AutogenKey; } }
private byte[] _ValidationKey;
private byte[] _DecryptionKey;
private bool DataInitialized = false;
internal byte[] ValidationKeyInternal { get { RuntimeDataInitialize(); return (byte[])_ValidationKey.Clone(); } }
internal byte[] DecryptionKeyInternal { get { RuntimeDataInitialize(); return (byte[])_DecryptionKey.Clone(); } }
#if UNUSED
static internal int ValidationKeyHashCode
{
get
{
EnsureConfig();
return ByteArrayToHexString(s_validationKey, s_validationKey.Length).GetHashCode();
}
}
#endif
static MachineKeySection()
{
// Property initialization
_properties = new ConfigurationPropertyCollection();
_properties.Add(_propValidationKey);
_properties.Add(_propDecryptionKey);
_properties.Add(_propValidation);
_properties.Add(_propDecryption);
_properties.Add(_propCompatibilityMode);
}
public MachineKeySection()
{
}
internal static MachineKeyCompatibilityMode CompatMode
{
get
{
EnsureConfig();
return s_compatMode;
}
}
protected override ConfigurationPropertyCollection Properties
{
get
{
return _properties;
}
}
[ConfigurationProperty("validationKey", DefaultValue = "AutoGenerate,IsolateApps")]
[TypeConverter(typeof(WhiteSpaceTrimStringConverter))]
[StringValidator(MinLength = 1)]
public string ValidationKey
{
get
{
return (string)base[_propValidationKey];
}
set
{
base[_propValidationKey] = value;
}
}
[ConfigurationProperty("decryptionKey", DefaultValue = "AutoGenerate,IsolateApps")]
[TypeConverter(typeof(WhiteSpaceTrimStringConverter))]
[StringValidator(MinLength = 1)]
public string DecryptionKey
{
get
{
return (string)base[_propDecryptionKey];
}
set
{
base[_propDecryptionKey] = value;
}
}
[ConfigurationProperty("decryption", DefaultValue = "Auto")]
[TypeConverter(typeof(WhiteSpaceTrimStringConverter))]
[StringValidator(MinLength = 1)]
public string Decryption {
get {
string s = base[_propDecryption] as string;
if (s == null)
return "Auto";
if (s != "Auto" && s != "AES" && s != "3DES" && s != "DES")
throw new ConfigurationErrorsException(SR.GetString(SR.Wrong_decryption_enum), ElementInformation.Properties["decryption"].Source, ElementInformation.Properties["decryption"].LineNumber);
return s;
}
set {
if (value != "AES" && value != "3DES" && value != "Auto" && value != "DES")
throw new ConfigurationErrorsException(SR.GetString(SR.Wrong_decryption_enum), ElementInformation.Properties["decryption"].Source, ElementInformation.Properties["decryption"].LineNumber);
base[_propDecryption] = value;
}
}
private bool _validationIsCached;
private MachineKeyValidation _cachedValidation;
[ConfigurationProperty("validation", DefaultValue = MachineKeyValidation.SHA1)]
[TypeConverter(typeof(MachineKeyValidationConverter ))]
public MachineKeyValidation Validation
{
get
{
if (_validationIsCached == false) {
_cachedValidation = (MachineKeyValidation)base[_propValidation];
_validationIsCached = true;
}
return _cachedValidation;
}
set
{
base[_propValidation] = value;
_cachedValidation = value;
_validationIsCached = true;
}
}
[ConfigurationProperty("compatibilityMode", DefaultValue = MachineKeyCompatibilityMode.Framework20SP1)]
public MachineKeyCompatibilityMode CompatibilityMode
{
get
{
return (MachineKeyCompatibilityMode)base[_propCompatibilityMode];
}
set
{
base[_propCompatibilityMode] = value;
}
}
protected override void Reset(ConfigurationElement parentElement)
{
MachineKeySection parent = parentElement as MachineKeySection;
base.Reset(parentElement);
// copy the privates from the parent.
if (parent != null)
{
// _ValidationKey = parent.ValidationKeyInternal;
// _DecryptionKey = parent.DecryptionKeyInternal;
// _AutogenKey = parent.AutogenKey;
}
}
private void RuntimeDataInitialize()
{
if (DataInitialized == false)
{
byte [] bKeysRandom = null;
bool fNonHttpApp = false;
string strKey = ValidationKey;
string appName = HttpRuntime.AppDomainAppVirtualPath;
if( appName == null )
{
#if !FEATURE_PAL // FEATURE_PAL does not enable cryptography
// FEATURE_PAL
appName = System.Diagnostics.Process.GetCurrentProcess().MainModule.ModuleName;
if( ValidationKey.Contains( "AutoGenerate" ) ||
DecryptionKey.Contains( "AutoGenerate" ) )
{
fNonHttpApp = true;
bKeysRandom = new byte[ BLOCK_SIZE + 24 ];
RNGCryptoServiceProvider randgen = new RNGCryptoServiceProvider();
// Gernerate random keys
randgen.GetBytes( bKeysRandom );
}
#endif // !FEATURE_PAL
}
bool fAppSpecific = StringUtil.StringEndsWith(strKey, ",IsolateApps");
if (fAppSpecific)
{
strKey = strKey.Substring(0, strKey.Length - ",IsolateApps".Length);
}
if (strKey == "AutoGenerate")
{ // case sensitive
_ValidationKey = new byte[BLOCK_SIZE];
if( fNonHttpApp )
{
Buffer.BlockCopy( bKeysRandom, 0, _ValidationKey, 0, BLOCK_SIZE);
}
else
{
Buffer.BlockCopy(HttpRuntime.s_autogenKeys, 0, _ValidationKey, 0, BLOCK_SIZE);
}
}
else
{
if (strKey.Length > 128 || strKey.Length < 40)
throw new ConfigurationErrorsException(SR.GetString(SR.Unable_to_get_cookie_authentication_validation_key, strKey.Length.ToString(CultureInfo.InvariantCulture)), ElementInformation.Properties["validationKey"].Source, ElementInformation.Properties["validationKey"].LineNumber);
_ValidationKey = HexStringToByteArray(strKey);
if (_ValidationKey == null)
throw new ConfigurationErrorsException(SR.GetString(SR.Invalid_validation_key), ElementInformation.Properties["validationKey"].Source, ElementInformation.Properties["validationKey"].LineNumber);
}
if (fAppSpecific)
{
int dwCode = StringComparer.InvariantCultureIgnoreCase.GetHashCode( appName );
_ValidationKey[0] = (byte)(dwCode & 0xff);
_ValidationKey[1] = (byte)((dwCode & 0xff00) >> 8);
_ValidationKey[2] = (byte)((dwCode & 0xff0000) >> 16);
_ValidationKey[3] = (byte)((dwCode & 0xff000000) >> 24);
}
strKey = DecryptionKey;
fAppSpecific = StringUtil.StringEndsWith(strKey, ",IsolateApps");
if (fAppSpecific)
{
strKey = strKey.Substring(0, strKey.Length - ",IsolateApps".Length);
}
if (strKey == "AutoGenerate")
{ // case sensitive
_DecryptionKey = new byte[24];
if( fNonHttpApp )
{
Buffer.BlockCopy( bKeysRandom, BLOCK_SIZE, _DecryptionKey, 0, 24);
}
else
{
Buffer.BlockCopy(HttpRuntime.s_autogenKeys, BLOCK_SIZE, _DecryptionKey, 0, 24);
}
_AutogenKey = true;
}
else
{
_AutogenKey = false;
if ((strKey.Length % 2) != 0)
throw new ConfigurationErrorsException(SR.GetString(SR.Invalid_decryption_key), ElementInformation.Properties["decryptionKey"].Source, ElementInformation.Properties["decryptionKey"].LineNumber);
_DecryptionKey = HexStringToByteArray(strKey);
if (_DecryptionKey == null)
throw new ConfigurationErrorsException(SR.GetString(SR.Invalid_decryption_key), ElementInformation.Properties["decryptionKey"].Source, ElementInformation.Properties["decryptionKey"].LineNumber);
}
if (fAppSpecific)
{
int dwCode = StringComparer.InvariantCultureIgnoreCase.GetHashCode(appName);
_DecryptionKey[0] = (byte)(dwCode & 0xff);
_DecryptionKey[1] = (byte)((dwCode & 0xff00) >> 8);
_DecryptionKey[2] = (byte)((dwCode & 0xff0000) >> 16);
_DecryptionKey[3] = (byte)((dwCode & 0xff000000) >> 24);
}
DataInitialized = true;
}
}
internal static byte[] EncryptOrDecryptData(bool fEncrypt, byte[] buf, byte[] modifier, int start, int length)
{
// DevDiv Bugs 137864: IVType.Hash is the default for compatibility reasons. It allows the result to be
// consistent across multiple calls with the same data. This was the behavior when there was no padding.
return EncryptOrDecryptData(fEncrypt, buf, modifier, start, length, IVType.Hash, false);
}
internal static byte[] EncryptOrDecryptData(bool fEncrypt, byte[] buf, byte[] modifier, int start, int length, bool useValidationSymAlgo)
{
// DevDiv Bugs 137864: IVType.Hash is the default for compatibility reasons. It allows the result to be
// consistent across multiple calls with the same data. This was the behavior when there was no padding.
return EncryptOrDecryptData(fEncrypt, buf, modifier, start, length, IVType.Hash, useValidationSymAlgo);
}
internal static byte[] EncryptOrDecryptData(bool fEncrypt, byte[] buf, byte[] modifier, int start, int length, IVType ivType)
{
return EncryptOrDecryptData(fEncrypt, buf, modifier, start, length, ivType, false);
}
internal static byte[] EncryptOrDecryptData(bool fEncrypt, byte[] buf, byte[] modifier, int start, int length, IVType ivType, bool useValidationSymAlgo)
{
EnsureConfig();
System.IO.MemoryStream ms = new System.IO.MemoryStream();
ICryptoTransform oDesEnc = GetCryptoTransform(fEncrypt, useValidationSymAlgo);
CryptoStream cs = new CryptoStream(ms, oDesEnc, CryptoStreamMode.Write);
// DevDiv Bugs 137864: Add Random or Hashed IV to beginning of data to be encrypted.
// IVType.None is used by MembershipProvider which requires compatibility even in SP2 mode.
bool createIV = ((ivType != IVType.None) && (CompatMode > MachineKeyCompatibilityMode.Framework20SP1));
if (fEncrypt && createIV)
{
byte[] iv = null;
switch (ivType)
{
case IVType.Hash:
iv = GetIVHash(buf, useValidationSymAlgo);
break;
case IVType.Random:
iv = GetIVRandom(useValidationSymAlgo);
break;
}
Debug.Assert(iv != null, "Invalid value for IVType: " + ivType.ToString("G"));
cs.Write(iv, 0, iv.Length);
}
cs.Write(buf, start, length);
if (fEncrypt && modifier != null)
{
cs.Write(modifier, 0, modifier.Length);
}
cs.FlushFinalBlock();
byte[] paddedData = ms.ToArray();
byte[] bData;
cs.Close();
ReturnCryptoTransform(fEncrypt, oDesEnc, useValidationSymAlgo);
// DevDiv Bugs 137864: Strip Random or Hashed IV from beginning of unencrypted data
if (!fEncrypt && createIV)
{
// strip off the first bytes that were either random bits or a hash of the original data
// either way it is always equal to the key length
int ivLength = GetIVLength(useValidationSymAlgo);
int bDataLength = paddedData.Length - ivLength;
// valid if the data is long enough to have included the padding
if (bDataLength >= 0)
{
bData = new byte[bDataLength];
// copy from the padded data to non-padded buffer bData.
// dont bother with copy if the data is entirely the padding
if (bDataLength > 0)
{
Buffer.BlockCopy(paddedData, ivLength, bData, 0, bDataLength);
}
}
else
{
// data is not padded because it is not long enough
bData = paddedData;
}
}
else
{
bData = paddedData;
}
if (!fEncrypt && modifier != null && modifier.Length > 0)
{
for(int iter=0; iter= s_validationKey.Length) {
// Buffer.BlockCopy(s_validationKey, 0, buf, start + length, s_validationKey.Length);
// byte[] computedHash = md5.ComputeHash(buf, start, length + s_validationKey.Length);
//
// // Cleanup validation key from buf
// for (int i = (start + length); i < (start + length + s_validationKey.Length); i++) {
// buf[i] = 0;
// }
//
// return computedHash;
// }
// }
byte[] bAll = new byte[totalLength];
Buffer.BlockCopy(buf, start, bAll, 0, length);
if (modifier != null)
{
Buffer.BlockCopy(modifier, 0, bAll, length, modifier.Length);
length += modifier.Length;
}
Buffer.BlockCopy(s_validationKey, 0, bAll, length, s_validationKey.Length);
return md5.ComputeHash(bAll);
}
private static void SetInnerOuterKeys(byte[] validationKey) {
byte[] key = null;
if (validationKey.Length > BLOCK_SIZE) {
key = new byte[HASH_SIZE];
int hr = UnsafeNativeMethods.GetSHA1Hash(validationKey, validationKey.Length, key, key.Length);
Marshal.ThrowExceptionForHR(hr);
}
if (s_inner == null)
s_inner = new byte[BLOCK_SIZE];
if (s_outer == null)
s_outer = new byte[BLOCK_SIZE];
int i;
for (i=0; i < BLOCK_SIZE; i++) {
s_inner[i] = 0x36;
s_outer[i] = 0x5C;
}
for (i=0; i < validationKey.Length; i++) {
s_inner[i] ^= validationKey[i];
s_outer[i] ^= validationKey[i];
}
}
private static byte[] GetHMACSHA1Hash(byte[] buf, byte[] modifier, int start, int length) {
if (length < 0 || buf == null || length > buf.Length)
throw new ArgumentException(SR.GetString(SR.InvalidArgumentValue, "length"));
if (start < 0 || start >= length)
throw new ArgumentException(SR.GetString(SR.InvalidArgumentValue, "start"));
byte[] buffer = new byte[HASH_SIZE];
int hr = UnsafeNativeMethods.GetHMACSHA1Hash(buf, start, length,
modifier, (modifier == null) ? 0 : modifier.Length,
s_inner, s_inner.Length, s_outer, s_outer.Length,
buffer, buffer.Length);
Marshal.ThrowExceptionForHR(hr);
return buffer;
}
internal static string HashAndBase64EncodeString(string s)
{
byte[] ab;
byte[] hash;
string result;
ab = Encoding.Unicode.GetBytes(s);
hash = HashData(ab, null, 0, ab.Length);
result = Convert.ToBase64String(hash);
return result;
}
static internal void DestroyByteArray(byte[] buf)
{
if (buf == null || buf.Length < 1)
return;
for (int iter = 0; iter < buf.Length; iter++)
buf[iter] = (byte)0;
}
internal void DestroyKeys()
{
MachineKeySection.DestroyByteArray(_ValidationKey);
MachineKeySection.DestroyByteArray(_DecryptionKey);
}
static char[] s_acharval;
static unsafe internal String ByteArrayToHexString(byte[] buf, int iLen)
{
char[] acharval = s_acharval;
if (acharval == null)
{
acharval = new char[16];
for (int i = acharval.Length; --i >= 0; )
{
if (i < 10)
{
acharval[i] = (char)('0' + i);
}
else
{
acharval[i] = (char)('A' + (i - 10));
}
}
s_acharval = acharval;
}
if (buf == null)
return null;
if (iLen == 0)
iLen = buf.Length;
char[] chars = new char[iLen * 2];
fixed (char* fc = chars, fcharval = acharval)
{
fixed (byte* fb = buf)
{
char* pc;
byte* pb;
pc = fc;
pb = fb;
while (--iLen >= 0)
{
*pc++ = fcharval[(*pb & 0xf0) >> 4];
*pc++ = fcharval[*pb & 0x0f];
pb++;
}
}
}
return new String(chars);
}
static void EnsureConfig()
{
if (s_config == null)
{
lock (s_initLock)
{
if (s_config == null)
{
MachineKeySection config = RuntimeConfig.GetAppConfig().MachineKey;
config.ConfigureEncryptionObject();
s_config = config;
s_compatMode = config.CompatibilityMode;
}
}
}
}
// NOTE: When encoding the data, this method *may* return the same reference to the input "buf" parameter
// with the hash appended in the end if there's enough space. The "length" parameter would also be
// appropriately adjusted in those cases. This is an optimization to prevent unnecessary copying of
// buffers.
internal static byte[] GetEncodedData(byte[] buf, byte[] modifier, int start, ref int length)
{
EnsureConfig();
byte[] bHash = HashData(buf, modifier, start, length);
byte[] returnBuffer;
if (buf.Length - start - length >= bHash.Length)
{
// Append hash to end of buffer if there's space
Buffer.BlockCopy(bHash, 0, buf, start + length, bHash.Length);
returnBuffer = buf;
}
else
{
returnBuffer = new byte[length + bHash.Length];
Buffer.BlockCopy(buf, start, returnBuffer, 0, length);
Buffer.BlockCopy(bHash, 0, returnBuffer, length, bHash.Length);
start = 0;
}
length += bHash.Length;
if (s_config.Validation == MachineKeyValidation.TripleDES || s_config.Validation == MachineKeyValidation.AES) {
returnBuffer = EncryptOrDecryptData(true, returnBuffer, modifier, start, length, true);
length = returnBuffer.Length;
}
return returnBuffer;
}
// NOTE: When decoding the data, this method *may* return the same reference to the input "buf" parameter
// with the "dataLength" parameter containing the actual length of the data in the "buf" (i.e. length of actual
// data is (total length of data - hash length)). This is an optimization to prevent unnecessary copying of buffers.
internal static byte[] GetDecodedData(byte[] buf, byte[] modifier, int start, int length, ref int dataLength)
{
EnsureConfig();
if (s_config.Validation == MachineKeyValidation.TripleDES || s_config.Validation == MachineKeyValidation.AES) {
buf = EncryptOrDecryptData(false, buf, modifier, start, length, true);
if (buf == null || buf.Length < HASH_SIZE)
throw new HttpException(SR.GetString(SR.Unable_to_validate_data));
length = buf.Length;
start = 0;
}
if (length < HASH_SIZE || start < 0 || start >= length)
throw new HttpException(SR.GetString(SR.Unable_to_validate_data));
byte[] bHash = HashData(buf, modifier, start, length - HASH_SIZE);
for (int iter = 0; iter < bHash.Length; iter++)
if (bHash[iter] != buf[start + length - HASH_SIZE + iter])
throw new HttpException(SR.GetString(SR.Unable_to_validate_data));
dataLength = length - HASH_SIZE;
return buf;
}
internal static byte[] HashData(byte[] buf, byte[] modifier, int start, int length)
{
EnsureConfig();
byte[] hash = null;
if (s_config.Validation == MachineKeyValidation.MD5)
hash = MD5HashForData(buf, modifier, start, length);
else
hash = GetHMACSHA1Hash(buf, modifier, start, length);
// We need to pad the returning hash so that they all have an uniform size (makes it easier when we decode)
// MD5 will return a 16 byte hash, whereas the default SHA1 returns 20, so we pad it with 4 zero bytes
System.Web.Util.Debug.Assert(hash.Length <= HASH_SIZE, "Hash size is greater than HASH_SIZE constant!");
if (hash.Length < HASH_SIZE)
{
byte[] tmp = new byte[HASH_SIZE];
Buffer.BlockCopy(hash, 0, tmp, 0, hash.Length);
hash = tmp;
}
return hash;
}
private void ConfigureEncryptionObject()
{
using (new ApplicationImpersonationContext()) {
s_validationKey = ValidationKeyInternal;
byte[] dKey = DecryptionKeyInternal;
SetInnerOuterKeys(s_validationKey);
DestroyKeys();
switch (Decryption) {
case "3DES":
s_oSymAlgoDecryption = new TripleDESCryptoServiceProvider();
break;
case "DES":
s_oSymAlgoDecryption = new DESCryptoServiceProvider();
break;
case "AES":
s_oSymAlgoDecryption = new RijndaelManaged();
break;
default: // "Auto" case
if (dKey.Length == 8) {
s_oSymAlgoDecryption = new DESCryptoServiceProvider();
} else {
s_oSymAlgoDecryption = new RijndaelManaged();
}
break;
}
switch(Validation)
{
case MachineKeyValidation.TripleDES:
if (dKey.Length == 8) {
s_oSymAlgoValidation = new DESCryptoServiceProvider();
} else {
s_oSymAlgoValidation = new TripleDESCryptoServiceProvider();
}
break;
case MachineKeyValidation.AES:
s_oSymAlgoValidation = new RijndaelManaged();
break;
}
if (s_oSymAlgoValidation != null) {
SetKeyOnSymAlgorithm(s_oSymAlgoValidation, dKey);
s_oEncryptorStackValidation = new Stack();
s_oDecryptorStackValidation = new Stack();
}
SetKeyOnSymAlgorithm(s_oSymAlgoDecryption, dKey);
s_oEncryptorStackDecryption = new Stack();
s_oDecryptorStackDecryption = new Stack();
DestroyByteArray(dKey);
}
}
private void SetKeyOnSymAlgorithm(SymmetricAlgorithm symAlgo, byte[] dKey)
{
try {
if (dKey.Length == 24 && symAlgo is DESCryptoServiceProvider) {
byte[] bTemp = new byte[8];
Buffer.BlockCopy(dKey, 0, bTemp, 0, 8);
symAlgo.Key = bTemp;
DestroyByteArray(bTemp);
} else {
symAlgo.Key = dKey;
}
symAlgo.GenerateIV();
symAlgo.IV = new byte[symAlgo.IV.Length];
} catch (Exception e) {
throw new ConfigurationErrorsException(SR.GetString(SR.Bad_machine_key, e.Message), ElementInformation.Properties["decryptionKey"].Source, ElementInformation.Properties["decryptionKey"].LineNumber);
}
}
private static ICryptoTransform GetCryptoTransform(bool fEncrypt, bool useValidationSymAlgo)
{
Stack st;
if (useValidationSymAlgo) {
st = (fEncrypt ? s_oEncryptorStackValidation : s_oDecryptorStackValidation);
} else {
st = (fEncrypt ? s_oEncryptorStackDecryption : s_oDecryptorStackDecryption);
}
lock (st) {
if (st.Count > 0)
return (ICryptoTransform)st.Pop();
}
if (useValidationSymAlgo) {
lock (s_oSymAlgoValidation) {
return (fEncrypt ? s_oSymAlgoValidation.CreateEncryptor() : s_oSymAlgoValidation.CreateDecryptor());
}
} else {
lock (s_oSymAlgoDecryption) {
return (fEncrypt ? s_oSymAlgoDecryption.CreateEncryptor() : s_oSymAlgoDecryption.CreateDecryptor());
}
}
}
private static void ReturnCryptoTransform(bool fEncrypt, ICryptoTransform ct, bool useValidationSymAlgo)
{
Stack st;
if (useValidationSymAlgo) {
st = (fEncrypt ? s_oEncryptorStackValidation : s_oDecryptorStackValidation);
} else {
st = (fEncrypt ? s_oEncryptorStackDecryption : s_oDecryptorStackDecryption);
}
lock (st) {
if (st.Count <= 100)
st.Push(ct);
}
}
static byte[] s_ahexval;
static internal byte[] HexStringToByteArray(String str)
{
if (((uint)str.Length & 0x1) == 0x1) // must be 2 nibbles per byte
{
return null;
}
byte[] ahexval = s_ahexval; // initialize a table for faster lookups
if (ahexval == null)
{
ahexval = new byte['f' + 1];
for (int i = ahexval.Length; --i >= 0; )
{
if ('0' <= i && i <= '9')
{
ahexval[i] = (byte)(i - '0');
}
else if ('a' <= i && i <= 'f')
{
ahexval[i] = (byte)(i - 'a' + 10);
}
else if ('A' <= i && i <= 'F')
{
ahexval[i] = (byte)(i - 'A' + 10);
}
}
s_ahexval = ahexval;
}
byte[] result = new byte[str.Length / 2];
int istr = 0, ir = 0;
int n = result.Length;
while (--n >= 0)
{
int c1, c2;
try
{
c1 = ahexval[str[istr++]];
}
catch (ArgumentNullException)
{
c1 = 0;
return null;// Inavlid char
}
catch (ArgumentException)
{
c1 = 0;
return null;// Inavlid char
}
catch (IndexOutOfRangeException)
{
c1 = 0;
return null;// Inavlid char
}
try
{
c2 = ahexval[str[istr++]];
}
catch (ArgumentNullException)
{
c2 = 0;
return null;// Inavlid char
}
catch (ArgumentException)
{
c2 = 0;
return null;// Inavlid char
}
catch (IndexOutOfRangeException)
{
c2 = 0;
return null;// Inavlid char
}
result[ir++] = (byte)((c1 << 4) + c2);
}
return result;
}
}
}
// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- UIElement.cs
- AttributeProviderAttribute.cs
- ResourceDefaultValueAttribute.cs
- ConfigUtil.cs
- FixedPageAutomationPeer.cs
- ObjectViewListener.cs
- CodeGenerator.cs
- XmlSerializer.cs
- FileLoadException.cs
- LowerCaseStringConverter.cs
- DataGridViewColumnCollection.cs
- ProtocolsSection.cs
- HttpInputStream.cs
- PropertyExpression.cs
- BasicKeyConstraint.cs
- KnownTypes.cs
- StreamGeometry.cs
- Walker.cs
- ClonableStack.cs
- DataTableTypeConverter.cs
- SqlDataSourceStatusEventArgs.cs
- DeferredTextReference.cs
- SQLDateTime.cs
- GridViewAutomationPeer.cs
- DataControlPagerLinkButton.cs
- Win32SafeHandles.cs
- ConfigurationManager.cs
- Pen.cs
- AdRotator.cs
- ISAPIWorkerRequest.cs
- FormViewRow.cs
- InputElement.cs
- X509ScopedServiceCertificateElementCollection.cs
- MetadataArtifactLoaderXmlReaderWrapper.cs
- UserValidatedEventArgs.cs
- ThrowHelper.cs
- CaseInsensitiveHashCodeProvider.cs
- BooleanProjectedSlot.cs
- AvTrace.cs
- UIElementPropertyUndoUnit.cs
- ValidatedMobileControlConverter.cs
- QueryContinueDragEventArgs.cs
- WebErrorHandler.cs
- DataServiceException.cs
- XmlHelper.cs
- SiteMapProvider.cs
- SqlDataSourceStatusEventArgs.cs
- bidPrivateBase.cs
- GraphicsContext.cs
- DataGridColumnHeader.cs
- ToolStripLabel.cs
- Keyboard.cs
- ScrollEvent.cs
- BridgeDataReader.cs
- Message.cs
- DataGridColumn.cs
- TCPListener.cs
- SubstitutionList.cs
- GeneralEndpointIdentity.cs
- CacheSection.cs
- NameValueCollection.cs
- Rotation3DAnimationBase.cs
- SafeFileMappingHandle.cs
- IPHostEntry.cs
- __Filters.cs
- XamlStream.cs
- NativeMethods.cs
- xamlnodes.cs
- SchemaDeclBase.cs
- TemplateContainer.cs
- ChtmlTextWriter.cs
- LightweightEntityWrapper.cs
- AspCompat.cs
- XPathSingletonIterator.cs
- DocumentationServerProtocol.cs
- SqlRewriteScalarSubqueries.cs
- SynchronizedInputHelper.cs
- WebConfigurationHostFileChange.cs
- DaylightTime.cs
- util.cs
- Button.cs
- TextProperties.cs
- OleDbMetaDataFactory.cs
- TableRowGroup.cs
- AuthenticatingEventArgs.cs
- BooleanSwitch.cs
- ProofTokenCryptoHandle.cs
- ReferencedCollectionType.cs
- CodeNamespaceCollection.cs
- EntryWrittenEventArgs.cs
- EntityDataSourceSelectedEventArgs.cs
- SmtpCommands.cs
- XPathAncestorQuery.cs
- CustomValidator.cs
- SymbolType.cs
- DesignerVerbCollection.cs
- ManualResetEvent.cs
- ContentAlignmentEditor.cs
- BasicViewGenerator.cs
- GraphicsContext.cs