CryptoHelper.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / IdentityModel / System / IdentityModel / CryptoHelper.cs / 1305376 / CryptoHelper.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.IdentityModel 
{
    using System.Collections.Generic; 
    using System.Collections.Specialized; 
    using System.Diagnostics;
    using System.IdentityModel.Tokens; 
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Reflection;
    using System.Security.Cryptography; 
    using System.Security.Cryptography.Xml;
    using System.Threading; 
 
    static class CryptoHelper
    { 
        static byte[] emptyBuffer;
        static RandomNumberGenerator random;
        static Rijndael rijndael;
        static TripleDES tripleDES; 

        static Dictionary> algorithmDelegateDictionary = new Dictionary>(); 
        static object AlgorithmDictionaryLock = new object(); 

        internal static byte[] EmptyBuffer 
        {
            get
            {
                if (emptyBuffer == null) 
                {
                    byte[] tmp = new byte[0]; 
                    emptyBuffer = tmp; 
                }
                return emptyBuffer; 
            }
        }

        internal static Rijndael Rijndael 
        {
            get 
            { 
                if (rijndael == null)
                { 
                    Rijndael tmp = SecurityUtils.RequiresFipsCompliance ? (Rijndael)new RijndaelCryptoServiceProvider() : new RijndaelManaged(); ;
                    tmp.Padding = PaddingMode.ISO10126;
                    rijndael = tmp;
                } 
                return rijndael;
            } 
        } 

        internal static TripleDES TripleDES 
        {
            get
            {
                if (tripleDES == null) 
                {
                    TripleDESCryptoServiceProvider tmp = new TripleDESCryptoServiceProvider(); 
                    tmp.Padding = PaddingMode.ISO10126; 
                    tripleDES = tmp;
                } 
                return tripleDES;
            }
        }
 
        internal static RandomNumberGenerator RandomNumberGenerator
        { 
            get 
            {
                if (random == null) 
                {
                    random = new RNGCryptoServiceProvider();
                }
                return random; 
            }
        } 
 
        internal static HashAlgorithm NewSha1HashAlgorithm()
        { 
            return CryptoHelper.CreateHashAlgorithm(SecurityAlgorithms.Sha1Digest);
        }

        internal static HashAlgorithm NewSha256HashAlgorithm() 
        {
            return CryptoHelper.CreateHashAlgorithm(SecurityAlgorithms.Sha256Digest); 
        } 

        internal static KeyedHashAlgorithm NewHmacSha1KeyedHashAlgorithm(byte[] key) 
        {
            return CryptoHelper.CreateKeyedHashAlgorithm(key, SecurityAlgorithms.HmacSha1Signature);
        }
 
        internal static KeyedHashAlgorithm NewHmacSha256KeyedHashAlgorithm(byte[] key)
        { 
            return CryptoHelper.CreateKeyedHashAlgorithm(key, SecurityAlgorithms.HmacSha256Signature); 
        }
 
        internal static Rijndael NewRijndaelSymmetricAlgorithm()
        {
            Rijndael rijndael = (GetSymmetricAlgorithm(null, SecurityAlgorithms.Aes128Encryption) as Rijndael);
            if (rijndael != null) 
                return rijndael;
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidSymmetricAlgorithm, SecurityAlgorithms.Aes128Encryption))); 
        } 

        internal static ICryptoTransform CreateDecryptor(byte[] key, byte[] iv, string algorithm) 
        {
            object algorithmObject = GetAlgorithmFromConfig(algorithm);

            if (algorithmObject != null) 
            {
                SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm; 
 
                if (symmetricAlgorithm != null)
                { 
                    return symmetricAlgorithm.CreateDecryptor(key, iv);
                }
                //NOTE: KeyedHashAlgorithms are symmetric in nature but we still throw if it is passed as an argument.
 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidSymmetricAlgorithm, algorithm)));
            } 
 
            switch (algorithm)
            { 
                case SecurityAlgorithms.TripleDesEncryption:
                    return TripleDES.CreateDecryptor(key, iv);
                case SecurityAlgorithms.Aes128Encryption:
                case SecurityAlgorithms.Aes192Encryption: 
                case SecurityAlgorithms.Aes256Encryption:
                    return Rijndael.CreateDecryptor(key, iv); 
                default: 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedEncryptionAlgorithm, algorithm)));
            } 
        }

        internal static ICryptoTransform CreateEncryptor(byte[] key, byte[] iv, string algorithm)
        { 

            object algorithmObject = GetAlgorithmFromConfig(algorithm); 
 
            if (algorithmObject != null)
            { 
                SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
                if (symmetricAlgorithm != null)
                {
                    return symmetricAlgorithm.CreateEncryptor(key, iv); 
                }
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidSymmetricAlgorithm, algorithm))); 
            } 

            switch (algorithm) 
            {
                case SecurityAlgorithms.TripleDesEncryption:
                    return TripleDES.CreateEncryptor(key, iv);
                case SecurityAlgorithms.Aes128Encryption: 
                case SecurityAlgorithms.Aes192Encryption:
                case SecurityAlgorithms.Aes256Encryption: 
                    return Rijndael.CreateEncryptor(key, iv); 
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedEncryptionAlgorithm, algorithm))); 
            }
        }

        internal static HashAlgorithm CreateHashAlgorithm(string algorithm) 
        {
            object algorithmObject = GetAlgorithmFromConfig(algorithm); 
 
            if (algorithmObject != null)
            { 
                HashAlgorithm hashAlgorithm = algorithmObject as HashAlgorithm;
                if (hashAlgorithm != null)
                {
                    return hashAlgorithm; 
                }
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidHashAlgorithm, algorithm))); 
            } 

            switch (algorithm) 
            {
                case SecurityAlgorithms.Sha1Digest:
                    if (SecurityUtils.RequiresFipsCompliance)
                        return new SHA1CryptoServiceProvider(); 
                    else
                        return new SHA1Managed(); 
 
                case SecurityAlgorithms.Sha256Digest:
                    if (SecurityUtils.RequiresFipsCompliance) 
                        return new SHA256CryptoServiceProvider();
                    else
                        return new SHA256Managed();
                default: 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedCryptoAlgorithm, algorithm)));
            } 
        } 

        internal static KeyedHashAlgorithm CreateKeyedHashAlgorithm(byte[] key, string algorithm) 
        {
            object algorithmObject = GetAlgorithmFromConfig(algorithm);

            if (algorithmObject != null) 
            {
                KeyedHashAlgorithm keyedHashAlgorithm = algorithmObject as KeyedHashAlgorithm; 
                if (keyedHashAlgorithm != null) 
                {
                    keyedHashAlgorithm.Key = key; 
                    return keyedHashAlgorithm;
                }

                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidKeyedHashAlgorithm, algorithm))); 
            }
 
            switch (algorithm) 
            {
                case SecurityAlgorithms.HmacSha1Signature: 
                    return new HMACSHA1(key, !SecurityUtils.RequiresFipsCompliance);
                case SecurityAlgorithms.HmacSha256Signature:
                    if (!SecurityUtils.RequiresFipsCompliance)
                        return new HMACSHA256(key); 
                    else
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CryptoAlgorithmIsNotFipsCompliant, algorithm))); 
                default: 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedCryptoAlgorithm, algorithm)));
            } 
        }

        internal static byte[] ComputeHash(byte[] buffer)
        { 
            using (HashAlgorithm hasher = CryptoHelper.NewSha1HashAlgorithm())
            { 
                return hasher.ComputeHash(buffer); 
            }
        } 

        internal static byte[] GenerateDerivedKey(byte[] key, string algorithm, byte[] label, byte[] nonce, int derivedKeySize, int position)
        {
            if ((algorithm != SecurityAlgorithms.Psha1KeyDerivation) && (algorithm != SecurityAlgorithms.Psha1KeyDerivationDec2005)) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedKeyDerivationAlgorithm, algorithm))); 
            } 
            return new Psha1DerivedKeyGenerator(key).GenerateDerivedKey(label, nonce, derivedKeySize, position);
        } 

        internal static int GetIVSize(string algorithm)
        {
            object algorithmObject = GetAlgorithmFromConfig(algorithm); 

            if (algorithmObject != null) 
            { 
                SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
                if (symmetricAlgorithm != null) 
                {
                    return symmetricAlgorithm.BlockSize;
                }
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidSymmetricAlgorithm, algorithm))); 
            }
 
            switch (algorithm) 
            {
                case SecurityAlgorithms.TripleDesEncryption: 
                    return TripleDES.BlockSize;
                case SecurityAlgorithms.Aes128Encryption:
                case SecurityAlgorithms.Aes192Encryption:
                case SecurityAlgorithms.Aes256Encryption: 
                    return Rijndael.BlockSize;
                default: 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedEncryptionAlgorithm, algorithm))); 
            }
        } 

        internal static SymmetricAlgorithm GetSymmetricAlgorithm(byte[] key, string algorithm)
        {
            SymmetricAlgorithm symmetricAlgorithm; 

            object algorithmObject = GetAlgorithmFromConfig(algorithm); 
 
            if (algorithmObject != null)
            { 
                symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
                if (symmetricAlgorithm != null)
                {
                    if (key != null) 
                    {
                        symmetricAlgorithm.Key = key; 
                    } 
                    return symmetricAlgorithm;
                } 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidSymmetricAlgorithm, algorithm)));
            }

            // NOTE: HMACSHA1 and HMACSHA256 ( KeyedHashAlgorithms ) are symmetric algorithms but they do not extend Symmetric class. 
            // Hence the function throws when they are passed as arguments.
 
            switch (algorithm) 
            {
                case SecurityAlgorithms.TripleDesEncryption: 
                case SecurityAlgorithms.TripleDesKeyWrap:
                    symmetricAlgorithm = new TripleDESCryptoServiceProvider();
                    break;
                case SecurityAlgorithms.Aes128Encryption: 
                case SecurityAlgorithms.Aes192Encryption:
                case SecurityAlgorithms.Aes256Encryption: 
                case SecurityAlgorithms.Aes128KeyWrap: 
                case SecurityAlgorithms.Aes192KeyWrap:
                case SecurityAlgorithms.Aes256KeyWrap: 
                    symmetricAlgorithm = SecurityUtils.RequiresFipsCompliance ? (Rijndael)new RijndaelCryptoServiceProvider() : new RijndaelManaged();
                    break;
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedEncryptionAlgorithm, algorithm))); 

            } 
 
            if (key != null)
            { 
                symmetricAlgorithm.Key = key;
            }
            return symmetricAlgorithm;
        } 

        internal static bool IsAsymmetricAlgorithm(string algorithm) 
        { 
            object algorithmObject = null;
 
            try
            {
                algorithmObject = GetAlgorithmFromConfig(algorithm);
            } 
            catch (InvalidOperationException)
            { 
                algorithmObject = null; 
                // We ---- the exception and continue.
            } 

            if (algorithmObject != null)
            {
                AsymmetricAlgorithm asymmetricAlgorithm = algorithmObject as AsymmetricAlgorithm; 
                SignatureDescription signatureDescription = algorithmObject as SignatureDescription;
                if (asymmetricAlgorithm != null || signatureDescription != null) 
                    return true; 
                return false;
            } 

            switch (algorithm)
            {
                case SecurityAlgorithms.DsaSha1Signature: 
                case SecurityAlgorithms.RsaSha1Signature:
                case SecurityAlgorithms.RsaSha256Signature: 
                case SecurityAlgorithms.RsaOaepKeyWrap: 
                case SecurityAlgorithms.RsaV15KeyWrap:
                    return true; 
                default:
                    return false;
            }
        } 

        internal static bool IsSymmetricAlgorithm(string algorithm) 
        { 
            object algorithmObject = null;
 
            try
            {
                algorithmObject = GetAlgorithmFromConfig(algorithm);
            } 
            catch (InvalidOperationException)
            { 
                algorithmObject = null; 
                // We ---- the exception and continue.
            } 
            if (algorithmObject != null)
            {
                SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
                KeyedHashAlgorithm keyedHashAlgorithm = algorithmObject as KeyedHashAlgorithm; 
                if (symmetricAlgorithm != null || keyedHashAlgorithm != null)
                    return true; 
                return false; 
            }
 
            // NOTE: A KeyedHashAlgorithm is symmetric in nature.

            switch (algorithm)
            { 
                case SecurityAlgorithms.DsaSha1Signature:
                case SecurityAlgorithms.RsaSha1Signature: 
                case SecurityAlgorithms.RsaSha256Signature: 
                case SecurityAlgorithms.RsaOaepKeyWrap:
                case SecurityAlgorithms.RsaV15KeyWrap: 
                    return false;
                case SecurityAlgorithms.HmacSha1Signature:
                case SecurityAlgorithms.HmacSha256Signature:
                case SecurityAlgorithms.Aes128Encryption: 
                case SecurityAlgorithms.Aes192Encryption:
                case SecurityAlgorithms.DesEncryption: 
                case SecurityAlgorithms.Aes256Encryption: 
                case SecurityAlgorithms.TripleDesEncryption:
                case SecurityAlgorithms.Aes128KeyWrap: 
                case SecurityAlgorithms.Aes192KeyWrap:
                case SecurityAlgorithms.Aes256KeyWrap:
                case SecurityAlgorithms.TripleDesKeyWrap:
                case SecurityAlgorithms.Psha1KeyDerivation: 
                case SecurityAlgorithms.Psha1KeyDerivationDec2005:
                    return true; 
                default: 
                    return false;
            } 
        }

        internal static bool IsSymmetricSupportedAlgorithm(string algorithm, int keySize)
        { 
            bool found = false;
            object algorithmObject = null; 
 
            try
            { 
                algorithmObject = GetAlgorithmFromConfig(algorithm);
            }
            catch (InvalidOperationException)
            { 
                // We ---- the exception and continue.
            } 
            if (algorithmObject != null) 
            {
                SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm; 
                KeyedHashAlgorithm keyedHashAlgorithm = algorithmObject as KeyedHashAlgorithm;

                if (symmetricAlgorithm != null || keyedHashAlgorithm != null)
                    found = true; 
                // The reason we do not return here even when the user has provided a custom algorithm in machine.config
                // is because we need to check if the user has overwritten an existing standard URI. 
            } 

            switch (algorithm) 
            {
                case SecurityAlgorithms.DsaSha1Signature:
                case SecurityAlgorithms.RsaSha1Signature:
                case SecurityAlgorithms.RsaSha256Signature: 
                case SecurityAlgorithms.RsaOaepKeyWrap:
                case SecurityAlgorithms.RsaV15KeyWrap: 
                    return false; 
                case SecurityAlgorithms.HmacSha1Signature:
                case SecurityAlgorithms.HmacSha256Signature: 
                case SecurityAlgorithms.Psha1KeyDerivation:
                case SecurityAlgorithms.Psha1KeyDerivationDec2005:
                    return true;
                case SecurityAlgorithms.Aes128Encryption: 
                case SecurityAlgorithms.Aes128KeyWrap:
                    return keySize >= 128 && keySize <= 256; 
                case SecurityAlgorithms.Aes192Encryption: 
                case SecurityAlgorithms.Aes192KeyWrap:
                    return keySize >= 192 && keySize <= 256; 
                case SecurityAlgorithms.Aes256Encryption:
                case SecurityAlgorithms.Aes256KeyWrap:
                    return keySize == 256;
                case SecurityAlgorithms.TripleDesEncryption: 
                case SecurityAlgorithms.TripleDesKeyWrap:
                    return keySize == 128 || keySize == 192; 
                default: 
                    if (found)
                        return true; 
                    return false;
                // We do not expect the user to map the uri of an existing standrad algorithm with say key size 128 bit
                // to a custom algorithm with keySize 192 bits. If he does that, we anyways make sure that we return false.
            } 
        }
 
        // We currently call the CLR APIs to do symmetric key wrap. 
        // This ends up causing a triple cloning of the byte arrays.
        // However, the symmetric key wrap exists now primarily for 
        // the feature completeness of cryptos and tokens.  That is,
        // it is never encountered in any Indigo AuthenticationMode.
        // The performance of this should be reviewed if this gets hit
        // in any mainline scenario. 
        internal static byte[] UnwrapKey(byte[] wrappingKey, byte[] wrappedKey, string algorithm)
        { 
            SymmetricAlgorithm symmetricAlgorithm; 
            object algorithmObject = GetAlgorithmFromConfig(algorithm);
            if (algorithmObject != null) 
            {
                symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
                if (symmetricAlgorithm == null)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.InvalidCustomKeyWrapAlgorithm, algorithm)));
                } 
                using (symmetricAlgorithm) 
                {
                    symmetricAlgorithm.Key = wrappingKey; 
                    return EncryptedXml.DecryptKey(wrappedKey, symmetricAlgorithm);
                }
            }
            switch (algorithm) 
            {
                case SecurityAlgorithms.TripleDesKeyWrap: 
                    symmetricAlgorithm = new TripleDESCryptoServiceProvider(); 
                    break;
                case SecurityAlgorithms.Aes128KeyWrap: 
                case SecurityAlgorithms.Aes192KeyWrap:
                case SecurityAlgorithms.Aes256KeyWrap:
                    symmetricAlgorithm = SecurityUtils.RequiresFipsCompliance ? (Rijndael)new RijndaelCryptoServiceProvider() : new RijndaelManaged();
                    break; 
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedKeyWrapAlgorithm, algorithm))); 
            } 

            using (symmetricAlgorithm) 
            {
                symmetricAlgorithm.Key = wrappingKey;
                return EncryptedXml.DecryptKey(wrappedKey, symmetricAlgorithm);
            } 
        }
 
        internal static byte[] WrapKey(byte[] wrappingKey, byte[] keyToBeWrapped, string algorithm) 
        {
            SymmetricAlgorithm symmetricAlgorithm; 
            object algorithmObject = GetAlgorithmFromConfig(algorithm);
            if (algorithmObject != null)
            {
                symmetricAlgorithm = algorithmObject as SymmetricAlgorithm; 
                if (symmetricAlgorithm == null)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.InvalidCustomKeyWrapAlgorithm, algorithm))); 
                }
                using (symmetricAlgorithm) 
                {
                    symmetricAlgorithm.Key = wrappingKey;
                    return EncryptedXml.EncryptKey(keyToBeWrapped, symmetricAlgorithm);
                } 
            }
 
            switch (algorithm) 
            {
                case SecurityAlgorithms.TripleDesKeyWrap: 
                    symmetricAlgorithm = new TripleDESCryptoServiceProvider();
                    break;
                case SecurityAlgorithms.Aes128KeyWrap:
                case SecurityAlgorithms.Aes192KeyWrap: 
                case SecurityAlgorithms.Aes256KeyWrap:
                    symmetricAlgorithm = SecurityUtils.RequiresFipsCompliance ? (Rijndael)new RijndaelCryptoServiceProvider() : new RijndaelManaged(); 
                    break; 
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedKeyWrapAlgorithm, algorithm))); 
            }

            using (symmetricAlgorithm)
            { 
                symmetricAlgorithm.Key = wrappingKey;
                return EncryptedXml.EncryptKey(keyToBeWrapped, symmetricAlgorithm); 
            } 
        }
 
        internal static void ValidateBufferBounds(Array buffer, int offset, int count)
        {
            if (buffer == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("buffer"));
            } 
            if (count < 0 || count > buffer.Length) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeInRange, 0, buffer.Length))); 
            }
            if (offset < 0 || offset > buffer.Length - count)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeInRange, 0, buffer.Length - count))); 
            }
        } 
 
        internal static bool IsEqual(byte[] a, byte[] b)
        { 
            if (ReferenceEquals(a, b))
            {
                return true;
            } 

            if (a == null || b == null || a.Length != b.Length) 
            { 
                return false;
            } 

            for (int i = 0; i < a.Length; i++)
            {
                if (a[i] != b[i]) 
                {
                    return false; 
                } 
            }
            return true; 
        }

        private static object GetDefaultAlgorithm(string algorithm)
        { 
            if (string.IsNullOrEmpty(algorithm))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("algorithm")); 
            }
 
            switch (algorithm)
            {
                //case SecurityAlgorithms.RsaSha1Signature:
                //case SecurityAlgorithms.DsaSha1Signature: 
                    // For these algorithms above, crypto config returns internal objects.
                    // As we cannot create those internal objects, we are returning null. 
                    // If no custom algorithm is plugged-in, at least these two algorithms 
                    // will be inside the delegate dictionary.
                case SecurityAlgorithms.Sha1Digest: 
                    if (SecurityUtils.RequiresFipsCompliance)
                        return new SHA1CryptoServiceProvider();
                    else
                        return new SHA1Managed(); 
                case SecurityAlgorithms.ExclusiveC14n:
                    return new XmlDsigExcC14NTransform(); 
                case SecurityAlgorithms.Sha256Digest: 
                    if (SecurityUtils.RequiresFipsCompliance)
                        return new SHA256CryptoServiceProvider(); 
                    else
                        return new SHA256Managed();
                case SecurityAlgorithms.Sha512Digest:
                    if (SecurityUtils.RequiresFipsCompliance) 
                        return new SHA512CryptoServiceProvider();
                    else 
                        return new SHA512Managed(); 
                case SecurityAlgorithms.Aes128Encryption:
                case SecurityAlgorithms.Aes192Encryption: 
                case SecurityAlgorithms.Aes256Encryption:
                case SecurityAlgorithms.Aes128KeyWrap:
                case SecurityAlgorithms.Aes192KeyWrap:
                case SecurityAlgorithms.Aes256KeyWrap: 
                    if (SecurityUtils.RequiresFipsCompliance)
                        return new RijndaelCryptoServiceProvider(); 
                    else 
                        return new RijndaelManaged();
                case SecurityAlgorithms.TripleDesEncryption: 
                case SecurityAlgorithms.TripleDesKeyWrap:
                    return new TripleDESCryptoServiceProvider();
                case SecurityAlgorithms.HmacSha1Signature:
                    byte[] key = new byte[64]; 
                    new RNGCryptoServiceProvider().GetBytes(key);
                    return new HMACSHA1(key, !SecurityUtils.RequiresFipsCompliance); 
                case SecurityAlgorithms.HmacSha256Signature: 
                    if (!SecurityUtils.RequiresFipsCompliance)
                        return new HMACSHA256(); 
                    return null;
                case SecurityAlgorithms.ExclusiveC14nWithComments:
                    return new XmlDsigExcC14NWithCommentsTransform();
                case SecurityAlgorithms.Ripemd160Digest: 
                    if (!SecurityUtils.RequiresFipsCompliance)
                        return new RIPEMD160Managed(); 
                    return null; 
                case SecurityAlgorithms.DesEncryption:
                    return new DESCryptoServiceProvider(); 
                default:
                    return null;
            }
        } 

        internal static object GetAlgorithmFromConfig(string algorithm) 
        { 
            if (string.IsNullOrEmpty(algorithm))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("algorithm"));
            }

            object algorithmObject = null; 
            object defaultObject = null;
            Func delegateFunction = null; 
 
            if (!algorithmDelegateDictionary.TryGetValue(algorithm, out delegateFunction))
            { 
                lock (AlgorithmDictionaryLock)
                {
                    if (!algorithmDelegateDictionary.ContainsKey(algorithm))
                    { 
                        try
                        { 
                            algorithmObject = CryptoConfig.CreateFromName(algorithm); 
                        }
                        catch (TargetInvocationException) 
                        {
                            algorithmDelegateDictionary[algorithm] = null;
                        }
 
                        if (algorithmObject == null)
                        { 
                            algorithmDelegateDictionary[algorithm] = null; 
                        }
                        else 
                        {
                            defaultObject = GetDefaultAlgorithm(algorithm);
                            if ((!SecurityUtils.RequiresFipsCompliance && algorithmObject is SHA1CryptoServiceProvider)
                                || (defaultObject != null && defaultObject.GetType() == algorithmObject.GetType())) 
                            {
                                algorithmDelegateDictionary[algorithm] = null; 
                            } 
                            else
                            { 

                                // Create a factory delegate which returns new instances of the algorithm type for later calls.
                                Type algorithmType = algorithmObject.GetType();
                                System.Linq.Expressions.NewExpression algorithmCreationExpression = System.Linq.Expressions.Expression.New(algorithmType); 
                                System.Linq.Expressions.LambdaExpression creationFunction = System.Linq.Expressions.Expression.Lambda>(algorithmCreationExpression);
                                delegateFunction = creationFunction.Compile() as Func; 
 
                                if (delegateFunction != null)
                                { 
                                    algorithmDelegateDictionary[algorithm] = delegateFunction;
                                }
                                return algorithmObject;
                            } 
                        }
                    } 
                } 
            }
            else 
            {
                if (delegateFunction != null)
                {
                    return delegateFunction.Invoke(); 
                }
            } 
            return null; 
        }
    } 
}


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.IdentityModel 
{
    using System.Collections.Generic; 
    using System.Collections.Specialized; 
    using System.Diagnostics;
    using System.IdentityModel.Tokens; 
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Reflection;
    using System.Security.Cryptography; 
    using System.Security.Cryptography.Xml;
    using System.Threading; 
 
    static class CryptoHelper
    { 
        static byte[] emptyBuffer;
        static RandomNumberGenerator random;
        static Rijndael rijndael;
        static TripleDES tripleDES; 

        static Dictionary> algorithmDelegateDictionary = new Dictionary>(); 
        static object AlgorithmDictionaryLock = new object(); 

        internal static byte[] EmptyBuffer 
        {
            get
            {
                if (emptyBuffer == null) 
                {
                    byte[] tmp = new byte[0]; 
                    emptyBuffer = tmp; 
                }
                return emptyBuffer; 
            }
        }

        internal static Rijndael Rijndael 
        {
            get 
            { 
                if (rijndael == null)
                { 
                    Rijndael tmp = SecurityUtils.RequiresFipsCompliance ? (Rijndael)new RijndaelCryptoServiceProvider() : new RijndaelManaged(); ;
                    tmp.Padding = PaddingMode.ISO10126;
                    rijndael = tmp;
                } 
                return rijndael;
            } 
        } 

        internal static TripleDES TripleDES 
        {
            get
            {
                if (tripleDES == null) 
                {
                    TripleDESCryptoServiceProvider tmp = new TripleDESCryptoServiceProvider(); 
                    tmp.Padding = PaddingMode.ISO10126; 
                    tripleDES = tmp;
                } 
                return tripleDES;
            }
        }
 
        internal static RandomNumberGenerator RandomNumberGenerator
        { 
            get 
            {
                if (random == null) 
                {
                    random = new RNGCryptoServiceProvider();
                }
                return random; 
            }
        } 
 
        internal static HashAlgorithm NewSha1HashAlgorithm()
        { 
            return CryptoHelper.CreateHashAlgorithm(SecurityAlgorithms.Sha1Digest);
        }

        internal static HashAlgorithm NewSha256HashAlgorithm() 
        {
            return CryptoHelper.CreateHashAlgorithm(SecurityAlgorithms.Sha256Digest); 
        } 

        internal static KeyedHashAlgorithm NewHmacSha1KeyedHashAlgorithm(byte[] key) 
        {
            return CryptoHelper.CreateKeyedHashAlgorithm(key, SecurityAlgorithms.HmacSha1Signature);
        }
 
        internal static KeyedHashAlgorithm NewHmacSha256KeyedHashAlgorithm(byte[] key)
        { 
            return CryptoHelper.CreateKeyedHashAlgorithm(key, SecurityAlgorithms.HmacSha256Signature); 
        }
 
        internal static Rijndael NewRijndaelSymmetricAlgorithm()
        {
            Rijndael rijndael = (GetSymmetricAlgorithm(null, SecurityAlgorithms.Aes128Encryption) as Rijndael);
            if (rijndael != null) 
                return rijndael;
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidSymmetricAlgorithm, SecurityAlgorithms.Aes128Encryption))); 
        } 

        internal static ICryptoTransform CreateDecryptor(byte[] key, byte[] iv, string algorithm) 
        {
            object algorithmObject = GetAlgorithmFromConfig(algorithm);

            if (algorithmObject != null) 
            {
                SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm; 
 
                if (symmetricAlgorithm != null)
                { 
                    return symmetricAlgorithm.CreateDecryptor(key, iv);
                }
                //NOTE: KeyedHashAlgorithms are symmetric in nature but we still throw if it is passed as an argument.
 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidSymmetricAlgorithm, algorithm)));
            } 
 
            switch (algorithm)
            { 
                case SecurityAlgorithms.TripleDesEncryption:
                    return TripleDES.CreateDecryptor(key, iv);
                case SecurityAlgorithms.Aes128Encryption:
                case SecurityAlgorithms.Aes192Encryption: 
                case SecurityAlgorithms.Aes256Encryption:
                    return Rijndael.CreateDecryptor(key, iv); 
                default: 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedEncryptionAlgorithm, algorithm)));
            } 
        }

        internal static ICryptoTransform CreateEncryptor(byte[] key, byte[] iv, string algorithm)
        { 

            object algorithmObject = GetAlgorithmFromConfig(algorithm); 
 
            if (algorithmObject != null)
            { 
                SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
                if (symmetricAlgorithm != null)
                {
                    return symmetricAlgorithm.CreateEncryptor(key, iv); 
                }
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidSymmetricAlgorithm, algorithm))); 
            } 

            switch (algorithm) 
            {
                case SecurityAlgorithms.TripleDesEncryption:
                    return TripleDES.CreateEncryptor(key, iv);
                case SecurityAlgorithms.Aes128Encryption: 
                case SecurityAlgorithms.Aes192Encryption:
                case SecurityAlgorithms.Aes256Encryption: 
                    return Rijndael.CreateEncryptor(key, iv); 
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedEncryptionAlgorithm, algorithm))); 
            }
        }

        internal static HashAlgorithm CreateHashAlgorithm(string algorithm) 
        {
            object algorithmObject = GetAlgorithmFromConfig(algorithm); 
 
            if (algorithmObject != null)
            { 
                HashAlgorithm hashAlgorithm = algorithmObject as HashAlgorithm;
                if (hashAlgorithm != null)
                {
                    return hashAlgorithm; 
                }
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidHashAlgorithm, algorithm))); 
            } 

            switch (algorithm) 
            {
                case SecurityAlgorithms.Sha1Digest:
                    if (SecurityUtils.RequiresFipsCompliance)
                        return new SHA1CryptoServiceProvider(); 
                    else
                        return new SHA1Managed(); 
 
                case SecurityAlgorithms.Sha256Digest:
                    if (SecurityUtils.RequiresFipsCompliance) 
                        return new SHA256CryptoServiceProvider();
                    else
                        return new SHA256Managed();
                default: 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedCryptoAlgorithm, algorithm)));
            } 
        } 

        internal static KeyedHashAlgorithm CreateKeyedHashAlgorithm(byte[] key, string algorithm) 
        {
            object algorithmObject = GetAlgorithmFromConfig(algorithm);

            if (algorithmObject != null) 
            {
                KeyedHashAlgorithm keyedHashAlgorithm = algorithmObject as KeyedHashAlgorithm; 
                if (keyedHashAlgorithm != null) 
                {
                    keyedHashAlgorithm.Key = key; 
                    return keyedHashAlgorithm;
                }

                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidKeyedHashAlgorithm, algorithm))); 
            }
 
            switch (algorithm) 
            {
                case SecurityAlgorithms.HmacSha1Signature: 
                    return new HMACSHA1(key, !SecurityUtils.RequiresFipsCompliance);
                case SecurityAlgorithms.HmacSha256Signature:
                    if (!SecurityUtils.RequiresFipsCompliance)
                        return new HMACSHA256(key); 
                    else
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CryptoAlgorithmIsNotFipsCompliant, algorithm))); 
                default: 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedCryptoAlgorithm, algorithm)));
            } 
        }

        internal static byte[] ComputeHash(byte[] buffer)
        { 
            using (HashAlgorithm hasher = CryptoHelper.NewSha1HashAlgorithm())
            { 
                return hasher.ComputeHash(buffer); 
            }
        } 

        internal static byte[] GenerateDerivedKey(byte[] key, string algorithm, byte[] label, byte[] nonce, int derivedKeySize, int position)
        {
            if ((algorithm != SecurityAlgorithms.Psha1KeyDerivation) && (algorithm != SecurityAlgorithms.Psha1KeyDerivationDec2005)) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedKeyDerivationAlgorithm, algorithm))); 
            } 
            return new Psha1DerivedKeyGenerator(key).GenerateDerivedKey(label, nonce, derivedKeySize, position);
        } 

        internal static int GetIVSize(string algorithm)
        {
            object algorithmObject = GetAlgorithmFromConfig(algorithm); 

            if (algorithmObject != null) 
            { 
                SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
                if (symmetricAlgorithm != null) 
                {
                    return symmetricAlgorithm.BlockSize;
                }
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidSymmetricAlgorithm, algorithm))); 
            }
 
            switch (algorithm) 
            {
                case SecurityAlgorithms.TripleDesEncryption: 
                    return TripleDES.BlockSize;
                case SecurityAlgorithms.Aes128Encryption:
                case SecurityAlgorithms.Aes192Encryption:
                case SecurityAlgorithms.Aes256Encryption: 
                    return Rijndael.BlockSize;
                default: 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedEncryptionAlgorithm, algorithm))); 
            }
        } 

        internal static SymmetricAlgorithm GetSymmetricAlgorithm(byte[] key, string algorithm)
        {
            SymmetricAlgorithm symmetricAlgorithm; 

            object algorithmObject = GetAlgorithmFromConfig(algorithm); 
 
            if (algorithmObject != null)
            { 
                symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
                if (symmetricAlgorithm != null)
                {
                    if (key != null) 
                    {
                        symmetricAlgorithm.Key = key; 
                    } 
                    return symmetricAlgorithm;
                } 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.CustomCryptoAlgorithmIsNotValidSymmetricAlgorithm, algorithm)));
            }

            // NOTE: HMACSHA1 and HMACSHA256 ( KeyedHashAlgorithms ) are symmetric algorithms but they do not extend Symmetric class. 
            // Hence the function throws when they are passed as arguments.
 
            switch (algorithm) 
            {
                case SecurityAlgorithms.TripleDesEncryption: 
                case SecurityAlgorithms.TripleDesKeyWrap:
                    symmetricAlgorithm = new TripleDESCryptoServiceProvider();
                    break;
                case SecurityAlgorithms.Aes128Encryption: 
                case SecurityAlgorithms.Aes192Encryption:
                case SecurityAlgorithms.Aes256Encryption: 
                case SecurityAlgorithms.Aes128KeyWrap: 
                case SecurityAlgorithms.Aes192KeyWrap:
                case SecurityAlgorithms.Aes256KeyWrap: 
                    symmetricAlgorithm = SecurityUtils.RequiresFipsCompliance ? (Rijndael)new RijndaelCryptoServiceProvider() : new RijndaelManaged();
                    break;
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedEncryptionAlgorithm, algorithm))); 

            } 
 
            if (key != null)
            { 
                symmetricAlgorithm.Key = key;
            }
            return symmetricAlgorithm;
        } 

        internal static bool IsAsymmetricAlgorithm(string algorithm) 
        { 
            object algorithmObject = null;
 
            try
            {
                algorithmObject = GetAlgorithmFromConfig(algorithm);
            } 
            catch (InvalidOperationException)
            { 
                algorithmObject = null; 
                // We ---- the exception and continue.
            } 

            if (algorithmObject != null)
            {
                AsymmetricAlgorithm asymmetricAlgorithm = algorithmObject as AsymmetricAlgorithm; 
                SignatureDescription signatureDescription = algorithmObject as SignatureDescription;
                if (asymmetricAlgorithm != null || signatureDescription != null) 
                    return true; 
                return false;
            } 

            switch (algorithm)
            {
                case SecurityAlgorithms.DsaSha1Signature: 
                case SecurityAlgorithms.RsaSha1Signature:
                case SecurityAlgorithms.RsaSha256Signature: 
                case SecurityAlgorithms.RsaOaepKeyWrap: 
                case SecurityAlgorithms.RsaV15KeyWrap:
                    return true; 
                default:
                    return false;
            }
        } 

        internal static bool IsSymmetricAlgorithm(string algorithm) 
        { 
            object algorithmObject = null;
 
            try
            {
                algorithmObject = GetAlgorithmFromConfig(algorithm);
            } 
            catch (InvalidOperationException)
            { 
                algorithmObject = null; 
                // We ---- the exception and continue.
            } 
            if (algorithmObject != null)
            {
                SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
                KeyedHashAlgorithm keyedHashAlgorithm = algorithmObject as KeyedHashAlgorithm; 
                if (symmetricAlgorithm != null || keyedHashAlgorithm != null)
                    return true; 
                return false; 
            }
 
            // NOTE: A KeyedHashAlgorithm is symmetric in nature.

            switch (algorithm)
            { 
                case SecurityAlgorithms.DsaSha1Signature:
                case SecurityAlgorithms.RsaSha1Signature: 
                case SecurityAlgorithms.RsaSha256Signature: 
                case SecurityAlgorithms.RsaOaepKeyWrap:
                case SecurityAlgorithms.RsaV15KeyWrap: 
                    return false;
                case SecurityAlgorithms.HmacSha1Signature:
                case SecurityAlgorithms.HmacSha256Signature:
                case SecurityAlgorithms.Aes128Encryption: 
                case SecurityAlgorithms.Aes192Encryption:
                case SecurityAlgorithms.DesEncryption: 
                case SecurityAlgorithms.Aes256Encryption: 
                case SecurityAlgorithms.TripleDesEncryption:
                case SecurityAlgorithms.Aes128KeyWrap: 
                case SecurityAlgorithms.Aes192KeyWrap:
                case SecurityAlgorithms.Aes256KeyWrap:
                case SecurityAlgorithms.TripleDesKeyWrap:
                case SecurityAlgorithms.Psha1KeyDerivation: 
                case SecurityAlgorithms.Psha1KeyDerivationDec2005:
                    return true; 
                default: 
                    return false;
            } 
        }

        internal static bool IsSymmetricSupportedAlgorithm(string algorithm, int keySize)
        { 
            bool found = false;
            object algorithmObject = null; 
 
            try
            { 
                algorithmObject = GetAlgorithmFromConfig(algorithm);
            }
            catch (InvalidOperationException)
            { 
                // We ---- the exception and continue.
            } 
            if (algorithmObject != null) 
            {
                SymmetricAlgorithm symmetricAlgorithm = algorithmObject as SymmetricAlgorithm; 
                KeyedHashAlgorithm keyedHashAlgorithm = algorithmObject as KeyedHashAlgorithm;

                if (symmetricAlgorithm != null || keyedHashAlgorithm != null)
                    found = true; 
                // The reason we do not return here even when the user has provided a custom algorithm in machine.config
                // is because we need to check if the user has overwritten an existing standard URI. 
            } 

            switch (algorithm) 
            {
                case SecurityAlgorithms.DsaSha1Signature:
                case SecurityAlgorithms.RsaSha1Signature:
                case SecurityAlgorithms.RsaSha256Signature: 
                case SecurityAlgorithms.RsaOaepKeyWrap:
                case SecurityAlgorithms.RsaV15KeyWrap: 
                    return false; 
                case SecurityAlgorithms.HmacSha1Signature:
                case SecurityAlgorithms.HmacSha256Signature: 
                case SecurityAlgorithms.Psha1KeyDerivation:
                case SecurityAlgorithms.Psha1KeyDerivationDec2005:
                    return true;
                case SecurityAlgorithms.Aes128Encryption: 
                case SecurityAlgorithms.Aes128KeyWrap:
                    return keySize >= 128 && keySize <= 256; 
                case SecurityAlgorithms.Aes192Encryption: 
                case SecurityAlgorithms.Aes192KeyWrap:
                    return keySize >= 192 && keySize <= 256; 
                case SecurityAlgorithms.Aes256Encryption:
                case SecurityAlgorithms.Aes256KeyWrap:
                    return keySize == 256;
                case SecurityAlgorithms.TripleDesEncryption: 
                case SecurityAlgorithms.TripleDesKeyWrap:
                    return keySize == 128 || keySize == 192; 
                default: 
                    if (found)
                        return true; 
                    return false;
                // We do not expect the user to map the uri of an existing standrad algorithm with say key size 128 bit
                // to a custom algorithm with keySize 192 bits. If he does that, we anyways make sure that we return false.
            } 
        }
 
        // We currently call the CLR APIs to do symmetric key wrap. 
        // This ends up causing a triple cloning of the byte arrays.
        // However, the symmetric key wrap exists now primarily for 
        // the feature completeness of cryptos and tokens.  That is,
        // it is never encountered in any Indigo AuthenticationMode.
        // The performance of this should be reviewed if this gets hit
        // in any mainline scenario. 
        internal static byte[] UnwrapKey(byte[] wrappingKey, byte[] wrappedKey, string algorithm)
        { 
            SymmetricAlgorithm symmetricAlgorithm; 
            object algorithmObject = GetAlgorithmFromConfig(algorithm);
            if (algorithmObject != null) 
            {
                symmetricAlgorithm = algorithmObject as SymmetricAlgorithm;
                if (symmetricAlgorithm == null)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.InvalidCustomKeyWrapAlgorithm, algorithm)));
                } 
                using (symmetricAlgorithm) 
                {
                    symmetricAlgorithm.Key = wrappingKey; 
                    return EncryptedXml.DecryptKey(wrappedKey, symmetricAlgorithm);
                }
            }
            switch (algorithm) 
            {
                case SecurityAlgorithms.TripleDesKeyWrap: 
                    symmetricAlgorithm = new TripleDESCryptoServiceProvider(); 
                    break;
                case SecurityAlgorithms.Aes128KeyWrap: 
                case SecurityAlgorithms.Aes192KeyWrap:
                case SecurityAlgorithms.Aes256KeyWrap:
                    symmetricAlgorithm = SecurityUtils.RequiresFipsCompliance ? (Rijndael)new RijndaelCryptoServiceProvider() : new RijndaelManaged();
                    break; 
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedKeyWrapAlgorithm, algorithm))); 
            } 

            using (symmetricAlgorithm) 
            {
                symmetricAlgorithm.Key = wrappingKey;
                return EncryptedXml.DecryptKey(wrappedKey, symmetricAlgorithm);
            } 
        }
 
        internal static byte[] WrapKey(byte[] wrappingKey, byte[] keyToBeWrapped, string algorithm) 
        {
            SymmetricAlgorithm symmetricAlgorithm; 
            object algorithmObject = GetAlgorithmFromConfig(algorithm);
            if (algorithmObject != null)
            {
                symmetricAlgorithm = algorithmObject as SymmetricAlgorithm; 
                if (symmetricAlgorithm == null)
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.InvalidCustomKeyWrapAlgorithm, algorithm))); 
                }
                using (symmetricAlgorithm) 
                {
                    symmetricAlgorithm.Key = wrappingKey;
                    return EncryptedXml.EncryptKey(keyToBeWrapped, symmetricAlgorithm);
                } 
            }
 
            switch (algorithm) 
            {
                case SecurityAlgorithms.TripleDesKeyWrap: 
                    symmetricAlgorithm = new TripleDESCryptoServiceProvider();
                    break;
                case SecurityAlgorithms.Aes128KeyWrap:
                case SecurityAlgorithms.Aes192KeyWrap: 
                case SecurityAlgorithms.Aes256KeyWrap:
                    symmetricAlgorithm = SecurityUtils.RequiresFipsCompliance ? (Rijndael)new RijndaelCryptoServiceProvider() : new RijndaelManaged(); 
                    break; 
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new InvalidOperationException(SR.GetString(SR.UnsupportedKeyWrapAlgorithm, algorithm))); 
            }

            using (symmetricAlgorithm)
            { 
                symmetricAlgorithm.Key = wrappingKey;
                return EncryptedXml.EncryptKey(keyToBeWrapped, symmetricAlgorithm); 
            } 
        }
 
        internal static void ValidateBufferBounds(Array buffer, int offset, int count)
        {
            if (buffer == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("buffer"));
            } 
            if (count < 0 || count > buffer.Length) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeInRange, 0, buffer.Length))); 
            }
            if (offset < 0 || offset > buffer.Length - count)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeInRange, 0, buffer.Length - count))); 
            }
        } 
 
        internal static bool IsEqual(byte[] a, byte[] b)
        { 
            if (ReferenceEquals(a, b))
            {
                return true;
            } 

            if (a == null || b == null || a.Length != b.Length) 
            { 
                return false;
            } 

            for (int i = 0; i < a.Length; i++)
            {
                if (a[i] != b[i]) 
                {
                    return false; 
                } 
            }
            return true; 
        }

        private static object GetDefaultAlgorithm(string algorithm)
        { 
            if (string.IsNullOrEmpty(algorithm))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("algorithm")); 
            }
 
            switch (algorithm)
            {
                //case SecurityAlgorithms.RsaSha1Signature:
                //case SecurityAlgorithms.DsaSha1Signature: 
                    // For these algorithms above, crypto config returns internal objects.
                    // As we cannot create those internal objects, we are returning null. 
                    // If no custom algorithm is plugged-in, at least these two algorithms 
                    // will be inside the delegate dictionary.
                case SecurityAlgorithms.Sha1Digest: 
                    if (SecurityUtils.RequiresFipsCompliance)
                        return new SHA1CryptoServiceProvider();
                    else
                        return new SHA1Managed(); 
                case SecurityAlgorithms.ExclusiveC14n:
                    return new XmlDsigExcC14NTransform(); 
                case SecurityAlgorithms.Sha256Digest: 
                    if (SecurityUtils.RequiresFipsCompliance)
                        return new SHA256CryptoServiceProvider(); 
                    else
                        return new SHA256Managed();
                case SecurityAlgorithms.Sha512Digest:
                    if (SecurityUtils.RequiresFipsCompliance) 
                        return new SHA512CryptoServiceProvider();
                    else 
                        return new SHA512Managed(); 
                case SecurityAlgorithms.Aes128Encryption:
                case SecurityAlgorithms.Aes192Encryption: 
                case SecurityAlgorithms.Aes256Encryption:
                case SecurityAlgorithms.Aes128KeyWrap:
                case SecurityAlgorithms.Aes192KeyWrap:
                case SecurityAlgorithms.Aes256KeyWrap: 
                    if (SecurityUtils.RequiresFipsCompliance)
                        return new RijndaelCryptoServiceProvider(); 
                    else 
                        return new RijndaelManaged();
                case SecurityAlgorithms.TripleDesEncryption: 
                case SecurityAlgorithms.TripleDesKeyWrap:
                    return new TripleDESCryptoServiceProvider();
                case SecurityAlgorithms.HmacSha1Signature:
                    byte[] key = new byte[64]; 
                    new RNGCryptoServiceProvider().GetBytes(key);
                    return new HMACSHA1(key, !SecurityUtils.RequiresFipsCompliance); 
                case SecurityAlgorithms.HmacSha256Signature: 
                    if (!SecurityUtils.RequiresFipsCompliance)
                        return new HMACSHA256(); 
                    return null;
                case SecurityAlgorithms.ExclusiveC14nWithComments:
                    return new XmlDsigExcC14NWithCommentsTransform();
                case SecurityAlgorithms.Ripemd160Digest: 
                    if (!SecurityUtils.RequiresFipsCompliance)
                        return new RIPEMD160Managed(); 
                    return null; 
                case SecurityAlgorithms.DesEncryption:
                    return new DESCryptoServiceProvider(); 
                default:
                    return null;
            }
        } 

        internal static object GetAlgorithmFromConfig(string algorithm) 
        { 
            if (string.IsNullOrEmpty(algorithm))
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("algorithm"));
            }

            object algorithmObject = null; 
            object defaultObject = null;
            Func delegateFunction = null; 
 
            if (!algorithmDelegateDictionary.TryGetValue(algorithm, out delegateFunction))
            { 
                lock (AlgorithmDictionaryLock)
                {
                    if (!algorithmDelegateDictionary.ContainsKey(algorithm))
                    { 
                        try
                        { 
                            algorithmObject = CryptoConfig.CreateFromName(algorithm); 
                        }
                        catch (TargetInvocationException) 
                        {
                            algorithmDelegateDictionary[algorithm] = null;
                        }
 
                        if (algorithmObject == null)
                        { 
                            algorithmDelegateDictionary[algorithm] = null; 
                        }
                        else 
                        {
                            defaultObject = GetDefaultAlgorithm(algorithm);
                            if ((!SecurityUtils.RequiresFipsCompliance && algorithmObject is SHA1CryptoServiceProvider)
                                || (defaultObject != null && defaultObject.GetType() == algorithmObject.GetType())) 
                            {
                                algorithmDelegateDictionary[algorithm] = null; 
                            } 
                            else
                            { 

                                // Create a factory delegate which returns new instances of the algorithm type for later calls.
                                Type algorithmType = algorithmObject.GetType();
                                System.Linq.Expressions.NewExpression algorithmCreationExpression = System.Linq.Expressions.Expression.New(algorithmType); 
                                System.Linq.Expressions.LambdaExpression creationFunction = System.Linq.Expressions.Expression.Lambda>(algorithmCreationExpression);
                                delegateFunction = creationFunction.Compile() as Func; 
 
                                if (delegateFunction != null)
                                { 
                                    algorithmDelegateDictionary[algorithm] = delegateFunction;
                                }
                                return algorithmObject;
                            } 
                        }
                    } 
                } 
            }
            else 
            {
                if (delegateFunction != null)
                {
                    return delegateFunction.Invoke(); 
                }
            } 
            return null; 
        }
    } 
}


// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

                        

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