internal ReadOnlyCollection<SecurityKey> ResolveSecurityKeys(Saml2Assertion assertion, SecurityTokenResolver resolver)
 {
   
     Saml2Subject subject = assertion.Subject;
   
     Saml2SubjectConfirmation confirmation = subject.SubjectConfirmations[0];
     if (confirmation.SubjectConfirmationData != null)
     {
         this.ValidateConfirmationData(confirmation.SubjectConfirmationData);
     }
     
     List<SecurityKey> list = new List<SecurityKey>();
     foreach (SecurityKeyIdentifier identifier in confirmation.SubjectConfirmationData.KeyIdentifiers)
     {
         SecurityKey key = null;
         foreach (SecurityKeyIdentifierClause clause in identifier)
         {
             if ((resolver != null) && resolver.TryResolveSecurityKey(clause, out key))
             {
                 list.Add(key);
                 break;
             }
         }
         if (key == null)
         {
             if (identifier.CanCreateKey)
             {
                 key = identifier.CreateKey();
                 list.Add(key);
                 continue;
             }
             list.Add(new SecurityKeyElement(identifier, resolver));
         }
     }
     return list.AsReadOnly();
 }
        internal static XmlDictionaryReader CreatePlaintextReaderFromEncryptedData(
                        XmlDictionaryReader reader,
                        SecurityTokenResolver serviceTokenResolver,
                        SecurityTokenSerializer keyInfoSerializer,
                        Collection<EncryptedKeyIdentifierClause> clauses,
                        out EncryptingCredentials encryptingCredentials)
        {
            if (reader == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("reader");
            }

            reader.MoveToContent();
            if (reader.IsEmptyElement)
            {
#pragma warning suppress 56504 // bogus - thinks reader.LocalName, reader.NamespaceURI need validation
                throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID3061, reader.LocalName, reader.NamespaceURI));
            }

            encryptingCredentials = null;

            XmlUtil.ValidateXsiType(reader, Saml2Constants.Types.EncryptedElementType, Saml2Constants.Namespace);

            reader.ReadStartElement();
            EncryptedDataElement encryptedData = new EncryptedDataElement(keyInfoSerializer);

            // <xenc:EncryptedData> 1
            encryptedData.ReadXml(reader);

            // <xenc:EncryptedKey> 0-oo
            reader.MoveToContent();
            while (reader.IsStartElement(XmlEncryptionConstants.Elements.EncryptedKey, XmlEncryptionConstants.Namespace))
            {
                SecurityKeyIdentifierClause skic;
                if (keyInfoSerializer.CanReadKeyIdentifierClause(reader))
                {
                    skic = keyInfoSerializer.ReadKeyIdentifierClause(reader);
                }
                else
                {
                    EncryptedKeyElement encryptedKey = new EncryptedKeyElement(keyInfoSerializer);
                    encryptedKey.ReadXml(reader);
                    skic = encryptedKey.GetClause();
                }

                EncryptedKeyIdentifierClause encryptedKeyClause = skic as EncryptedKeyIdentifierClause;
                if (null == encryptedKeyClause)
                {
                    throw DiagnosticUtility.ThrowHelperXml(reader, SR.GetString(SR.ID4172));
                }

                clauses.Add(encryptedKeyClause);
            }

            reader.ReadEndElement();

            // Try to resolve the decryption key from both the embedded 
            // KeyInfo and any external clauses
            SecurityKey decryptionKey = null;
            SecurityKeyIdentifierClause matchingClause = null;

            foreach (SecurityKeyIdentifierClause clause in encryptedData.KeyIdentifier)
            {
                if (serviceTokenResolver.TryResolveSecurityKey(clause, out decryptionKey))
                {
                    matchingClause = clause;
                    break;
                }
            }

            if (null == decryptionKey)
            {
                foreach (SecurityKeyIdentifierClause clause in clauses)
                {
                    if (serviceTokenResolver.TryResolveSecurityKey(clause, out decryptionKey))
                    {
                        matchingClause = clause;
                        break;
                    }
                }
            }

            if (null == decryptionKey)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new EncryptedTokenDecryptionFailedException());
            }

            // Need a symmetric key
            SymmetricSecurityKey symmetricKey = decryptionKey as SymmetricSecurityKey;
            if (null == symmetricKey)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new SecurityTokenException(SR.GetString(SR.ID4023)));
            }

            // Do the actual decryption
            SymmetricAlgorithm decryptor = symmetricKey.GetSymmetricAlgorithm(encryptedData.Algorithm);
            byte[] plainText = encryptedData.Decrypt(decryptor);

            // Save off the encrypting credentials for roundtrip
            encryptingCredentials = new ReceivedEncryptingCredentials(decryptionKey, new SecurityKeyIdentifier(matchingClause), encryptedData.Algorithm);

            return XmlDictionaryReader.CreateTextReader(plainText, reader.Quotas);
        }
        /// <summary>
        /// Resolves the collection of <see cref="SecurityKey"/> referenced in a <see cref="Saml2Assertion"/>.
        /// </summary>
        /// <param name="assertion"><see cref="Saml2Assertion"/> to process.</param>
        /// <param name="resolver"><see cref="SecurityTokenResolver"/> to use in resolving the <see cref="SecurityKey"/>.</param>
        /// <returns>A read only collection of <see cref="SecurityKey"/> contained in the assertion.</returns>
        protected virtual ReadOnlyCollection<SecurityKey> ResolveSecurityKeys(Saml2Assertion assertion, SecurityTokenResolver resolver)
        {
            if (null == assertion)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("assertion");
            }

            // Must have Subject
            Saml2Subject subject = assertion.Subject;
            if (null == subject)
            {
                // No Subject
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4130)));
            }

            // Must have one SubjectConfirmation
            if (0 == subject.SubjectConfirmations.Count)
            {
                // No SubjectConfirmation
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4131)));
            }

            if (subject.SubjectConfirmations.Count > 1)
            {
                // More than one SubjectConfirmation
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4132)));
            }

            // Extract the keys for the given method
            ReadOnlyCollection<SecurityKey> securityKeys;

            Saml2SubjectConfirmation subjectConfirmation = subject.SubjectConfirmations[0];

            // For bearer, ensure there are no keys, set the collection to empty
            // For HolderOfKey, ensure there is at least one key, resolve and create collection
            if (Saml2Constants.ConfirmationMethods.Bearer == subjectConfirmation.Method)
            {
                if (null != subjectConfirmation.SubjectConfirmationData
                    && 0 != subjectConfirmation.SubjectConfirmationData.KeyIdentifiers.Count)
                {
                    // Bearer but has keys
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4133)));
                }

                securityKeys = EmptyReadOnlyCollection<SecurityKey>.Instance;
            }
            else if (Saml2Constants.ConfirmationMethods.HolderOfKey == subjectConfirmation.Method)
            {
                if (null == subjectConfirmation.SubjectConfirmationData
                    || 0 == subjectConfirmation.SubjectConfirmationData.KeyIdentifiers.Count)
                {
                    // Holder-of-key but no keys
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4134)));
                }

                List<SecurityKey> holderKeys = new List<SecurityKey>();
                SecurityKey key;

                foreach (SecurityKeyIdentifier keyIdentifier in subjectConfirmation.SubjectConfirmationData.KeyIdentifiers)
                {
                    key = null;

                    // Try the resolver first
                    foreach (SecurityKeyIdentifierClause clause in keyIdentifier)
                    {
                        if (null != resolver
                            && resolver.TryResolveSecurityKey(clause, out key))
                        {
                            holderKeys.Add(key);
                            break;
                        }
                    }

                    // If that doesn't work, try to create the key (e.g. bare RSA or X509 raw)
                    if (null == key)
                    {
                        if (keyIdentifier.CanCreateKey)
                        {
                            key = keyIdentifier.CreateKey();
                            holderKeys.Add(key);
                        }
                        else
                        {
                            holderKeys.Add(new SecurityKeyElement(keyIdentifier, resolver));
                        }
                    }
                }

                securityKeys = holderKeys.AsReadOnly();
            }
            else
            {
                // SenderVouches, as well as other random things, aren't accepted
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new SecurityTokenException(SR.GetString(SR.ID4136, subjectConfirmation.Method)));
            }

            return securityKeys;
        }
        internal static SecurityKey ResolveSecurityKey(SecurityKeyIdentifier ski, SecurityTokenResolver tokenResolver)
        {
            if (ski == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("ski");

            if (tokenResolver != null)
            {
                for (int i = 0; i < ski.Count; ++i)
                {
                    SecurityKey key = null;
                    if (tokenResolver.TryResolveSecurityKey(ski[i], out key))
                        return key;
                }
            }

            if (ski.CanCreateKey)
                return ski.CreateKey();

            return null;
        }