/// <summary>
        /// Reads the SessionSecurityToken from the given reader.
        /// </summary>
        /// <param name="reader">XmlReader over the SessionSecurityToken.</param>
        /// <param name="tokenResolver">SecurityTokenResolver that can used to resolve SessionSecurityToken.</param>
        /// <returns>An instance of <see cref="SessionSecurityToken"/>.</returns> 
        /// <exception cref="ArgumentNullException">The input argument 'reader' is null.</exception>
        /// <exception cref="SecurityTokenException">The 'reader' is not positioned at a SessionSecurityToken
        /// or the SessionSecurityToken cannot be read.</exception>
        public override SecurityToken ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver)
        {
            if (reader == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
            }

            if (tokenResolver == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenResolver");
            }

            byte[] encodedCookie = null;
            SysUniqueId contextId = null;
            SysUniqueId keyGeneration = null;

            string ns = null;
            string identifier = null;
            string instance = null;

            SecurityToken securityContextToken = null;
            SessionDictionary dictionary = SessionDictionary.Instance;

            XmlDictionaryReader dicReader = XmlDictionaryReader.CreateDictionaryReader(reader);

            if (dicReader.IsStartElement(WSSecureConversationFeb2005Constants.ElementNames.Name, WSSecureConversationFeb2005Constants.Namespace))
            {
                ns = WSSecureConversationFeb2005Constants.Namespace;
                identifier = WSSecureConversationFeb2005Constants.ElementNames.Identifier;
                instance = WSSecureConversationFeb2005Constants.ElementNames.Instance;
            }
            else if (dicReader.IsStartElement(WSSecureConversation13Constants.ElementNames.Name, WSSecureConversation13Constants.Namespace))
            {
                ns = WSSecureConversation13Constants.Namespace;
                identifier = WSSecureConversation13Constants.ElementNames.Identifier;
                instance = WSSecureConversation13Constants.ElementNames.Instance;
            }
            else
            {
                //
                // Something is wrong
                //
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(
                    SR.GetString(SR.ID4230, WSSecureConversationFeb2005Constants.ElementNames.Name, dicReader.Name)));
            }

            string id = dicReader.GetAttribute(WSUtilityConstants.Attributes.IdAttribute, WSUtilityConstants.NamespaceURI);

            dicReader.ReadFullStartElement();
            if (!dicReader.IsStartElement(identifier, ns))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(
                    SR.GetString(SR.ID4230, WSSecureConversation13Constants.ElementNames.Identifier, dicReader.Name)));
            }

            contextId = dicReader.ReadElementContentAsUniqueId();
            if (contextId == null || string.IsNullOrEmpty(contextId.ToString()))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4242)));
            }

            //
            // The token can be a renewed token, in which case we need to know the
            // instance id, which will be the secondary key to the context id for 
            // cache lookups
            //
            if (dicReader.IsStartElement(instance, ns))
            {
                keyGeneration = dicReader.ReadElementContentAsUniqueId();
            }

            if (dicReader.IsStartElement(CookieElementName, CookieNamespace))
            {
                // Get the token from the Cache, which is returned as an SCT
                SecurityToken cachedToken = null;

                SecurityContextKeyIdentifierClause sctClause = null;
                if (keyGeneration == null)
                {
                    sctClause = new SecurityContextKeyIdentifierClause(contextId);
                }
                else
                {
                    sctClause = new SecurityContextKeyIdentifierClause(contextId, keyGeneration);
                }

                tokenResolver.TryResolveToken(sctClause, out cachedToken);

                if (cachedToken != null)
                {
                    securityContextToken = cachedToken;

                    dicReader.Skip();
                }
                else
                {
                    //
                    // CookieMode
                    //
                    encodedCookie = dicReader.ReadElementContentAsBase64();

                    if (encodedCookie == null)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4237)));
                    }
                    //
                    // appply transforms
                    //
                    byte[] decodedCookie = ApplyTransforms(encodedCookie, false);

                    using (MemoryStream ms = new MemoryStream(decodedCookie))
                    {
                        BinaryFormatter formatter = new BinaryFormatter();
                        securityContextToken = formatter.Deserialize(ms) as SecurityToken;
                    }

                    SessionSecurityToken sessionToken = securityContextToken as SessionSecurityToken;
                    if (sessionToken != null && sessionToken.ContextId != contextId)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4229, sessionToken.ContextId, contextId)));
                    }

                    if (sessionToken != null && sessionToken.Id != id)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4227, sessionToken.Id, id)));
                    }
                }
            }
            else
            {
                //
                // SessionMode
                //

                // Get the token from the Cache.
                SecurityToken cachedToken = null;

                SecurityContextKeyIdentifierClause sctClause = null;
                if (keyGeneration == null)
                {
                    sctClause = new SecurityContextKeyIdentifierClause(contextId);
                }
                else
                {
                    sctClause = new SecurityContextKeyIdentifierClause(contextId, keyGeneration);
                }

                tokenResolver.TryResolveToken(sctClause, out cachedToken);

                if (cachedToken != null)
                {
                    securityContextToken = cachedToken;
                }
            }

            dicReader.ReadEndElement();

            if (securityContextToken == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4243)));
            }

            return securityContextToken;
        }
        protected static bool TryResolveKeyIdentifier(
            SecurityKeyIdentifier keyIdentifier, SecurityTokenResolver resolver, bool isFromSignature, out SecurityToken token)
        {
            if (keyIdentifier == null)
            {
                if (isFromSignature)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NoKeyInfoInSignatureToFindVerificationToken)));
                }
                else
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new MessageSecurityException(SR.GetString(SR.NoKeyInfoInEncryptedItemToFindDecryptingToken)));
                }
            }

            return resolver.TryResolveToken(keyIdentifier, out token);
        }
        /// <summary>
        /// Resolves the Signing Key Identifier to a SecurityToken.
        /// </summary>
        /// <param name="assertion">The Assertion for which the Issuer token is to be resolved.</param>
        /// <param name="issuerResolver">The current SecurityTokenResolver associated with this handler.</param>
        /// <param name="token">Resolved token.</param>
        /// <returns>True if token is resolved.</returns>
        protected virtual bool TryResolveIssuerToken(Saml2Assertion assertion, SecurityTokenResolver issuerResolver, out SecurityToken token)
        {
            if (null == assertion)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("assertion");
            }

            if (assertion.SigningCredentials != null
                && assertion.SigningCredentials.SigningKeyIdentifier != null
                && issuerResolver != null)
            {
                SecurityKeyIdentifier keyIdentifier = assertion.SigningCredentials.SigningKeyIdentifier;
                return issuerResolver.TryResolveToken(keyIdentifier, out token);
            }
            else
            {
                token = null;
                return false;
            }
        }
        internal static SecurityToken ResolveSecurityToken(SecurityKeyIdentifier ski, SecurityTokenResolver tokenResolver)
        {
            SecurityToken token = null;

            if (tokenResolver != null)
            {
                tokenResolver.TryResolveToken(ski, out token);
            }

            if (token == null)
            {
                // Check if this is a RSA key.
                RsaKeyIdentifierClause rsaClause;
                if (ski.TryFind<RsaKeyIdentifierClause>(out rsaClause))
                    token = new RsaSecurityToken(rsaClause.Rsa);
            }

            if (token == null)
            {
                // Check if this is a X509RawDataKeyIdentifier Clause.
                X509RawDataKeyIdentifierClause rawDataKeyIdentifierClause;
                if (ski.TryFind<X509RawDataKeyIdentifierClause>(out rawDataKeyIdentifierClause))
                    token = new X509SecurityToken(new X509Certificate2(rawDataKeyIdentifierClause.GetX509RawData()));
            }

            return token;
        }
 internal static SecurityToken ResolveSecurityToken(SecurityKeyIdentifier ski, SecurityTokenResolver tokenResolver)
 {
     SecurityToken token = null;
     RsaKeyIdentifierClause clause;
     X509RawDataKeyIdentifierClause clause2;
     if (tokenResolver != null)
     {
         tokenResolver.TryResolveToken(ski, out token);
     }
     if ((token == null) && ski.TryFind<RsaKeyIdentifierClause>(out clause))
     {
         token = new RsaSecurityToken(clause.Rsa);
     }
     if ((token == null) && ski.TryFind<X509RawDataKeyIdentifierClause>(out clause2))
     {
         token = new X509SecurityToken(new X509Certificate2(clause2.GetX509RawData()));
     }
     return token;
 }
            // xml format
            //<DerivedKeyToken wsu:Id="..." wsse:Algorithm="..."> id required, alg optional (curr disallowed)
            //  <SecurityTokenReference>...</SecurityTokenReference> - required
            //  <Properties>...</Properties> - disallowed (optional in spec, but we disallow it)
            // choice begin - (schema requires a choice - we allow neither on read - we always write one)
            //  <Generation>...</Generation> - optional
            //  <Offset>...</Offset> - optional
            // choice end
            //  <Length>...</Length> - optional - default 32 on read (default specified in spec, not in schema - we always write it)
            //  <Label>...</Label> - optional
            //  <Nonce>...</Nonce> - required (optional in spec, but we require it)
            //</DerivedKeyToken>
            public virtual void ReadDerivedKeyTokenParameters(XmlDictionaryReader reader, SecurityTokenResolver tokenResolver, out string id, out string derivationAlgorithm, out string label, out int length, out byte[] nonce, out int offset, out int generation, out SecurityKeyIdentifierClause tokenToDeriveIdentifier, out SecurityToken tokenToDerive)
            {
                if (tokenResolver == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("tokenResolver");
                }

                id = reader.GetAttribute(XD.UtilityDictionary.IdAttribute, XD.UtilityDictionary.Namespace);

                derivationAlgorithm = reader.GetAttribute(XD.XmlSignatureDictionary.Algorithm, null);
                if (derivationAlgorithm == null)
                {
                    derivationAlgorithm = parent.DerivationAlgorithm;
                }

                reader.ReadStartElement();

                tokenToDeriveIdentifier = null;
                tokenToDerive = null;

                if (reader.IsStartElement(XD.SecurityJan2004Dictionary.SecurityTokenReference, XD.SecurityJan2004Dictionary.Namespace))
                {
                    tokenToDeriveIdentifier = parent.WSSecurityTokenSerializer.ReadKeyIdentifierClause(reader);
                    tokenResolver.TryResolveToken(tokenToDeriveIdentifier, out tokenToDerive);
                }
                else
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.DerivedKeyTokenRequiresTokenReference)));
                }

                // no support for properties

                generation = -1;
                if (reader.IsStartElement(parent.SerializerDictionary.Generation, parent.SerializerDictionary.Namespace))
                {
                    reader.ReadStartElement();
                    generation = reader.ReadContentAsInt();
                    reader.ReadEndElement();
                    if (generation < 0)
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.DerivedKeyInvalidGenerationSpecified, generation)));
                }

                offset = -1;
                if (reader.IsStartElement(parent.SerializerDictionary.Offset, parent.SerializerDictionary.Namespace))
                {
                    reader.ReadStartElement();
                    offset = reader.ReadContentAsInt();
                    reader.ReadEndElement();
                    if (offset < 0)
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.DerivedKeyInvalidOffsetSpecified, offset)));
                }

                length = DerivedKeySecurityToken.DefaultDerivedKeyLength;
                if (reader.IsStartElement(parent.SerializerDictionary.Length, parent.SerializerDictionary.Namespace))
                {
                    reader.ReadStartElement();
                    length = reader.ReadContentAsInt();
                    reader.ReadEndElement();
                }

                if ((offset == -1) && (generation == -1))
                    offset = 0;

                // verify that the offset is not larger than the max allowed
                DerivedKeySecurityToken.EnsureAcceptableOffset(offset, generation, length, this.maxKeyDerivationOffset);

                label = null;
                if (reader.IsStartElement(parent.SerializerDictionary.Label, parent.SerializerDictionary.Namespace))
                {
                    reader.ReadStartElement();
                    label = reader.ReadString();
                    reader.ReadEndElement();
                }
                if (label != null && label.Length > this.maxKeyDerivationLabelLength)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.DerivedKeyTokenLabelTooLong, label.Length, this.maxKeyDerivationLabelLength)));
                }

                nonce = null;
                reader.ReadStartElement(parent.SerializerDictionary.Nonce, parent.SerializerDictionary.Namespace);
                nonce = reader.ReadContentAsBase64();
                reader.ReadEndElement();

                if (nonce != null && nonce.Length > this.maxKeyDerivationNonceLength)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new MessageSecurityException(SR.GetString(SR.DerivedKeyTokenNonceTooLong, nonce.Length, this.maxKeyDerivationNonceLength)));
                }

                reader.ReadEndElement();
            }