/// <summary>
        /// Checks the container is valid.
        /// </summary>
        /// <param name="containerDoc">Signed container.</param>
        /// <exception cref="ArgumentException">Thrown when the container is not valid.
        /// </exception>
        private void CheckSignedContainer(XmlDocument containerDoc)
        {
            // Check the document is a signed container
            if (!XmlUtils.CheckElement(containerDoc.DocumentElement, SignedPayloadElement,
                                       this.signedPayloadXmlNs))
            {
                throw new ArgumentException("Document is not a signed container");
            }

            XmlNamespaceManager namespaceManager =
                CreateXmlNamespaceManager(containerDoc);

            // Check the container has signatures
            IList <XmlElement> signatureElems = XPathUtils.GetElements(containerDoc,
                                                                       "/sp:signedPayload/sp:signatures/ds:Signature", namespaceManager);

            if (signatureElems.Count == 0)
            {
                throw new XspException("No signatures were found in the signed container");
            }

            // Check the container contains data
            if (XPathUtils.GetElement(containerDoc,
                                      "/sp:signedPayload/sp:signedPayloadData", namespaceManager) == null)
            {
                throw new XspException("No data section within the container");
            }
        }
        /// <summary>
        /// Gets a list of digest values.
        /// </summary>
        /// <param name="containerDoc">Signed container.</param>
        /// <returns>List of digest values.</returns>
        public IList <byte[]> GetDigestValues(XmlDocument containerDoc)
        {
            ArgumentUtils.CheckNotNull(containerDoc, "containerDoc");

            // Check the document is a signed container
            if (!XmlUtils.CheckElement(containerDoc.DocumentElement, SignedPayloadElement,
                                       this.signedPayloadXmlNs))
            {
                throw new ArgumentException("Document is not a signed container");
            }

            // Create the namespace manager for executing XPath statements
            XmlNamespaceManager namespaceManager = CreateXmlNamespaceManager(
                containerDoc);

            // Get the list of signature elements
            IList <XmlElement> signatureElems = XPathUtils.GetElements(containerDoc,
                                                                       "/sp:signedPayload/sp:signatures/ds:Signature", namespaceManager);

            if (signatureElems.Count == 0)
            {
                throw new XspException("No 'ds:Signature' elements were found within the " +
                                       "'sp:signatures' element");
            }

            // Iterate through each signature to get the digest
            IList <byte[]> digestList = new List <byte[]>();

            foreach (XmlElement signatureElem in signatureElems)
            {
                // Extract the digest from the signature
                IDictionary <string, byte[]> digestValues =
                    this.signedProfileService.GetDigestValues(signatureElem);

                if (digestValues.Keys.Count == 0)
                {
                    throw new XspException("Signature contains no refences");
                }

                if (digestValues.Keys.Count > 1)
                {
                    throw new XspException("Signature contains more than one reference");
                }

                // Get the first value from the values list as there is only one
                IEnumerator <byte[]> digestEnumerator =
                    digestValues.Values.GetEnumerator();
                digestEnumerator.MoveNext();
                digestList.Add(digestEnumerator.Current);
            }

            return(digestList);
        }
        /// <summary>
        /// Decrypts an encrypted container Xml element, returning the payload.
        /// </summary>
        /// <param name="encryptedPayloadElem">Encrypted container to decrypt.</param>
        /// <param name="certificate">Certificate to decrypt with.</param>
        /// <returns>Decrypted payload.</returns>
        /// <exception cref="XspException">Thrown on error.</exception>
        public XmlDocument GetData(XmlElement encryptedPayloadElem,
                                   X509Certificate2 certificate)
        {
            ArgumentUtils.CheckNotNull(encryptedPayloadElem, "encryptedPayloadElem");
            ArgumentUtils.CheckNotNull(certificate, "certificate");

            // Check the root element belongs to the right namespace
            if (!XmlUtils.CheckElement(encryptedPayloadElem, EncryptedPayloadElement,
                                       this.encryptedPayloadXmlNs))
            {
                throw new ArgumentException("Document is not an encrypted container");
            }

            // Clone the source element so it is not modified
            XmlElement clonePayloadElem = XmlUtils.Clone(encryptedPayloadElem);

            // Create a namespace manager for XPath
            XmlNamespaceManager namespaceManager = CreateXmlNamespaceManager(
                clonePayloadElem.OwnerDocument);

            // Get the 'xenc:EncryptedData' element
            XmlElement encryptedDataElem = XPathUtils.GetElement(clonePayloadElem,
                                                                 "/ep:encryptedPayload/ep:encryptedPayloadData/xenc:EncryptedData",
                                                                 namespaceManager);

            if (encryptedDataElem == null)
            {
                throw new XspException("Encrypted data was not found within the container");
            }

            // Get the 'xenc:EncryptedKey' element list
            IList <XmlElement> keyElems = XPathUtils.GetElements(clonePayloadElem,
                                                                 "/ep:encryptedPayload/ep:keys/xenc:EncryptedKey", namespaceManager);

            if (keyElems.Count == 0)
            {
                throw new XspException("No encrypted keys found within the container");
            }

            // Decrypt the data
            this.encryptedProfileService.Decrypt(keyElems, encryptedDataElem,
                                                 certificate);

            // Get the payload element
            XmlElement payloadElem = XPathUtils.GetElement(clonePayloadElem,
                                                           "/ep:encryptedPayload/ep:encryptedPayloadData/*[1]", namespaceManager);

            // Return the payload element within a new Xml document
            return(XmlUtils.CreateXmlDocument(payloadElem));
        }
        /// <summary>
        /// Checks the signatures in a signed payload container and also verifies the
        /// certificates with the certificate verifier callback.
        /// </summary>
        /// <param name="containerDoc">Signed payload container.</param>
        /// <param name="certificateVerifier">Certificate verifier.</param>
        /// <exception cref="XspException">Thrown on error.</exception>
        public void Check(XmlDocument containerDoc,
                          ICertificateVerifier certificateVerifier)
        {
            ArgumentUtils.CheckNotNull(containerDoc, "containerDoc");
            ArgumentUtils.CheckNotNull(certificateVerifier, "certificateVerifier");

            // Check the container is valid
            CheckSignedContainer(containerDoc);

            // Get all the signatures in the container
            IList <XmlElement> signatureElems = XPathUtils.GetElements(containerDoc,
                                                                       "/sp:signedPayload/sp:signatures/ds:Signature",
                                                                       CreateXmlNamespaceManager(containerDoc));

            // Check all the signatures verify
            this.signedProfileService.Check(signatureElems, certificateVerifier);
        }
        /// <summary>
        /// Returns a list of certificates from the signed container.
        /// </summary>
        /// <param name="containerDoc">Signed container.</param>
        /// <returns>List of certificates.</returns>
        public IList <X509Certificate2> GetSigningCertificates(XmlDocument containerDoc)
        {
            ArgumentUtils.CheckNotNull(containerDoc, "containerDoc");

            // Check the document is a signed container
            if (!XmlUtils.CheckElement(containerDoc.DocumentElement, SignedPayloadElement,
                                       this.signedPayloadXmlNs))
            {
                throw new ArgumentException("Document is not a signed container");
            }

            // Create the namespace manager for executing XPath statements
            XmlNamespaceManager namespaceManager = CreateXmlNamespaceManager(
                containerDoc);

            // Get the list of signature elements
            IList <XmlElement> signatureElems = XPathUtils.GetElements(containerDoc,
                                                                       "/sp:signedPayload/sp:signatures/ds:Signature", namespaceManager);

            if (signatureElems.Count == 0)
            {
                throw new XspException("No 'ds:Signature' elements were found " +
                                       "within the 'sp:signatures' element");
            }

            IList <X509Certificate2> certs = new List <X509Certificate2>();

            foreach (XmlElement signatureElem in signatureElems)
            {
                // Add each certificate
                X509Certificate2 cert =
                    this.signedProfileService.GetSigningCertificate(signatureElem);

                certs.Add(cert);
            }

            return(certs);
        }