/// <summary>
        /// Validates the presence and correctness of a <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#"/> among the any-xml-elements of a SubjectConfirmationData
        /// </summary>
        /// <param name="subjectConfirmationData"></param>
        public void ValidateKeyInfo(SubjectConfirmationData subjectConfirmationData)
        {
            if (subjectConfirmationData == null)
                throw new Saml20FormatException("SubjectConfirmationData cannot be null when KeyInfo subelements are required");

            if (subjectConfirmationData.AnyElements == null)
                throw new Saml20FormatException(String.Format("SubjectConfirmationData element MUST have at least one {0} subelement", KeyInfo.ELEMENT_NAME));

            bool keyInfoFound = false;
            foreach (XmlElement element in subjectConfirmationData.AnyElements)
            {
                if (element.NamespaceURI != Saml20Constants.XMLDSIG || element.LocalName != KeyInfo.ELEMENT_NAME)
                    continue;

                keyInfoFound = true;

                // A KeyInfo element MUST identify a cryptographic key
                if (!element.HasChildNodes)
                    throw new Saml20FormatException(String.Format("{0} subelement of SubjectConfirmationData MUST NOT be empty", KeyInfo.ELEMENT_NAME));
            }

            // There MUST BE at least one <ds:KeyInfo> element present (from the arbitrary elements list on SubjectConfirmationData
            if (!keyInfoFound)
                throw new Saml20FormatException(String.Format("SubjectConfirmationData element MUST contain at least one {0} in namespace {1}", KeyInfo.ELEMENT_NAME, Saml20Constants.XMLDSIG));
        }
        /// <summary>
        /// [SAML2.0std] section 2.4.1.2
        /// </summary>
        /// <param name="subjectConfirmationData"></param>
        public void ValidateSubjectConfirmationData(SubjectConfirmationData subjectConfirmationData)
        {
            // If present it must be anyUri
            if (subjectConfirmationData.Recipient != null)
            {
                if (!Uri.IsWellFormedUriString(subjectConfirmationData.Recipient, UriKind.Absolute))
                    throw new Saml20FormatException("Recipient of SubjectConfirmationData must be a wellformed absolute URI.");
            }

            // NotBefore MUST BE striclty less than NotOnOrAfter if they are both set
            if (subjectConfirmationData.NotBefore != null && subjectConfirmationData.NotBefore.HasValue
                && subjectConfirmationData.NotOnOrAfter != null && subjectConfirmationData.NotOnOrAfter.HasValue)
            {
                if (!(subjectConfirmationData.NotBefore < subjectConfirmationData.NotOnOrAfter))
                    throw new Saml20FormatException(String.Format("NotBefore {0} MUST BE less than NotOnOrAfter {1} on SubjectConfirmationData", Saml20Utils.ToUTCString(subjectConfirmationData.NotBefore.Value), Saml20Utils.ToUTCString(subjectConfirmationData.NotOnOrAfter.Value)));
            }

            // Make sure the extension-attributes are namespace-qualified and do not use reserved namespaces
            if (subjectConfirmationData.AnyAttr != null)
                AnyAttrValidator.ValidateXmlAnyAttributes(subjectConfirmationData.AnyAttr);

            // Standards-defined extension type which has stricter rules than it's base type
            if (subjectConfirmationData is KeyInfoConfirmationData)
                KeyInfoValidator.ValidateKeyInfo(subjectConfirmationData);
        }
        public void SubjectConfirmationDataValidTimeIntervalSettings()
        {
            Saml20SubjectConfirmationDataValidator validator = new Saml20SubjectConfirmationDataValidator();

            SubjectConfirmationData subjectConfirmationData = new SubjectConfirmationData();
            subjectConfirmationData.NotBefore = new DateTime(2008, 01, 30, 17, 13, 0, 500, DateTimeKind.Utc);
            subjectConfirmationData.NotOnOrAfter = subjectConfirmationData.NotBefore.Value.AddHours(1);

            validator.ValidateSubjectConfirmationData(subjectConfirmationData);

            subjectConfirmationData.NotBefore = null;
            validator.ValidateSubjectConfirmationData(subjectConfirmationData);

            // DateTime validation wrt DateTime.UtcNow is NOT done by the validators
            // so a future-NotBefore must be valid
            subjectConfirmationData.NotBefore = subjectConfirmationData.NotOnOrAfter;
            subjectConfirmationData.NotOnOrAfter = null;
            validator.ValidateSubjectConfirmationData(subjectConfirmationData);

            subjectConfirmationData.NotBefore = null;
            validator.ValidateSubjectConfirmationData(subjectConfirmationData);
        }
        public void SubjectConfirmationDataInvalidTimeInterval()
        {
            SubjectConfirmationData subjectConfirmationData = new SubjectConfirmationData();
            subjectConfirmationData.NotBefore = new DateTime(2008, 01, 30, 17, 13, 0, 500, DateTimeKind.Utc);
            subjectConfirmationData.NotOnOrAfter = subjectConfirmationData.NotBefore.Value.AddHours(-1);

            Saml20SubjectConfirmationDataValidator validator = new Saml20SubjectConfirmationDataValidator();
            validator.ValidateSubjectConfirmationData(subjectConfirmationData);
        }
        public void SubjectConfirmationDataValidRecipient()
        {
            SubjectConfirmationData subjectConfirmationData = new SubjectConfirmationData();
            subjectConfirmationData.Recipient = "urn:wellformed.uri:ok";

            Saml20SubjectConfirmationDataValidator validator = new Saml20SubjectConfirmationDataValidator();
            validator.ValidateSubjectConfirmationData(subjectConfirmationData);


        }
        public void SubjectConfirmationDataInvalidRecipient()
        {
            SubjectConfirmationData subjectConfirmationData = new SubjectConfirmationData();
            subjectConfirmationData.Recipient = "malformed uri";

            Saml20SubjectConfirmationDataValidator validator = new Saml20SubjectConfirmationDataValidator();
            validator.ValidateSubjectConfirmationData(subjectConfirmationData);
        }
        public void SubjectConfirmationDataEmptyRecipient()
        {
            SubjectConfirmationData subjectConfirmationData = new SubjectConfirmationData();
            subjectConfirmationData.Recipient = " ";

            Saml20SubjectConfirmationDataValidator validator = new Saml20SubjectConfirmationDataValidator();
            validator.ValidateSubjectConfirmationData(subjectConfirmationData);
        }