void ValidateTokensByParameters(IEnumerable <SecurityTokenParameters> plist, List <SupportingTokenInfo> tokens, bool optional, SecurityTokenAttachmentMode attachMode)
        {
            foreach (SecurityTokenParameters p in plist)
            {
                SecurityTokenResolver      r;
                SecurityTokenAuthenticator a =
                    security.CreateTokenAuthenticator(p, out r);
                SupportingTokenSpecification spec = ValidateTokensByParameters(a, r, tokens);
                if (spec == null)
                {
                    if (optional)
                    {
                        continue;
                    }
                    else
                    {
                        throw new MessageSecurityException(String.Format("No security token could be validated for authenticator '{0}' which is indicated by the '{1}' supporting token parameters", a, attachMode));
                    }
                }
                else
                {
                    // For endorsing tokens, verify corresponding signatures.
                    switch (attachMode)
                    {
                    case SecurityTokenAttachmentMode.Endorsing:
                    case SecurityTokenAttachmentMode.SignedEndorsing:
                        WSSignedXml esxml = GetSignatureForToken(spec.SecurityToken);
                        if (esxml == null)
                        {
                            throw new MessageSecurityException(String.Format("The '{1}' token '{0}' is expected to endorse the primary signature but no corresponding signature is found.", spec.SecurityToken, attachMode));
                        }

                        bool confirmed;
                        SecurityAlgorithmSuite suite = security.Element.DefaultAlgorithmSuite;
                        foreach (SecurityTokenReferenceKeyInfo kic in esxml.KeyInfo)
                        {
                            SecurityKey          signKey = spec.SecurityToken.ResolveKeyIdentifierClause(kic.Clause);
                            SymmetricSecurityKey symkey  = signKey as SymmetricSecurityKey;
                            if (symkey != null)
                            {
                                confirmed = esxml.CheckSignature(symkey.GetKeyedHashAlgorithm(suite.DefaultSymmetricSignatureAlgorithm));
                            }
                            else
                            {
                                AsymmetricAlgorithm alg = ((AsymmetricSecurityKey)signKey).GetAsymmetricAlgorithm(suite.DefaultAsymmetricSignatureAlgorithm, false);
                                confirmed = esxml.CheckSignature(alg);
                            }
                            if (!confirmed)
                            {
                                throw new MessageSecurityException(String.Format("Signature for '{1}' token '{0}' is invalid.", spec.SecurityToken, attachMode));
                            }
                            break;
                        }

                        sec_prop.ConfirmedSignatures.Insert(0, Convert.ToBase64String(esxml.SignatureValue));
                        break;
                    }
                }

                sec_prop.IncomingSupportingTokens.Add(spec);
            }
        }
        void ExtractSecurity()
        {
            if (security.MessageProtectionOrder == MessageProtectionOrder.SignBeforeEncryptAndEncryptSignature &&
                wss_header.Find <SignedXml> () != null)
            {
                throw new MessageSecurityException("The security binding element expects that the message signature is encrypted, while it isn't.");
            }

            WrappedKeySecurityToken wk = wss_header.Find <WrappedKeySecurityToken> ();
            DerivedKeySecurityToken dk = wss_header.Find <DerivedKeySecurityToken> ();

            if (wk != null)
            {
                if (Parameters.RequireDerivedKeys && dk == null)
                {
                    throw new MessageSecurityException("DerivedKeyToken is required in this contract, but was not found in the message");
                }
            }
            else
            {
                // FIXME: this is kind of hack for symmetric reply processing.
                wk = RequestSecurity.ProtectionToken != null ? RequestSecurity.ProtectionToken.SecurityToken as WrappedKeySecurityToken : null;
            }

            SymmetricSecurityKey wkkey = wk != null ? wk.SecurityKeys [0] as SymmetricSecurityKey : null;

            wss_header_reader.DecryptSecurity(this, wkkey, RequestSecurity != null ? RequestSecurity.EncryptionKey : null);

            // signature confirmation
            WSSignedXml sxml = wss_header.Find <WSSignedXml> ();

            if (sxml == null)
            {
                throw new MessageSecurityException("The the message signature is expected but not found.");
            }

            bool confirmed = false;

            SecurityKeyIdentifierClause sigClause = null;

            foreach (KeyInfoClause kic in sxml.KeyInfo)
            {
                SecurityTokenReferenceKeyInfo r = kic as SecurityTokenReferenceKeyInfo;
                if (r != null)
                {
                    sigClause = r.Clause;
                }
            }
            if (sigClause == null)
            {
                throw new MessageSecurityException("SecurityTokenReference was not found in dsig:Signature KeyInfo.");
            }

            SecurityToken signToken;
            SecurityKey   signKey;

            signToken = TokenResolver.ResolveToken(sigClause);
            signKey   = signToken.ResolveKeyIdentifierClause(sigClause);
            SymmetricSecurityKey symkey = signKey as SymmetricSecurityKey;

            if (symkey != null)
            {
                confirmed = sxml.CheckSignature(new HMACSHA1(symkey.GetSymmetricKey()));
                if (wk != null)
                {
                    // FIXME: authenticate token
                    sec_prop.ProtectionToken = new SecurityTokenSpecification(wk, null);
                }
            }
            else
            {
                AsymmetricAlgorithm alg = ((AsymmetricSecurityKey)signKey).GetAsymmetricAlgorithm(security.DefaultSignatureAlgorithm, false);
                confirmed = sxml.CheckSignature(alg);
                sec_prop.InitiatorToken = new SecurityTokenSpecification(
                    signToken,
                    security.TokenAuthenticator.ValidateToken(signToken));
            }
            if (!confirmed)
            {
                throw new MessageSecurityException("Message signature is invalid.");
            }

            // token authentication
            // FIXME: it might not be limited to recipient
            if (Direction == MessageDirection.Input)
            {
                ProcessSupportingTokens(sxml);
            }

            sec_prop.EncryptionKey = ((SymmetricSecurityKey)wk.SecurityKeys [0]).GetSymmetricKey();
            sec_prop.ConfirmedSignatures.Add(Convert.ToBase64String(sxml.SignatureValue));
        }