MachineKeySection.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ FXUpdate3074 / FXUpdate3074 / 1.1 / DEVDIV / depot / DevDiv / releases / whidbey / QFE / ndp / fx / src / xsp / System / Web / Configuration / MachineKeySection.cs / 4 / 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;
                    }
                }
            } 
        }
 
        // 

 

        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;
        }

        // 

 
        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.
//------------------------------------------------------------------------------ 
// 
//     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;
                    }
                }
            } 
        }
 
        // 

 

        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;
        }

        // 

 
        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.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK