예제 #1
0
        /// <summary>
        /// Returns the <see cref="XmlElement" /> object with the specified ID from the specified <see cref="XmlDocument" /> object.
        /// </summary>
        /// <param name="document">The <see cref="XmlDocument" /> object to retrieve the <see cref="XmlElement" /> object from.</param>
        /// <param name="idValue">The ID of the <see cref="T:System.Xml.XmlElement" /> object to retrieve from the <see cref="XmlDocument" /> object.</param>
        /// <returns>The <see cref="XmlElement" /> object with the specified ID from the specified <see cref="XmlDocument" /> object, or null if it could not be found.</returns>
        public override XmlElement GetIdElement(
            XmlDocument document,
            string idValue)
        {
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }
            if (idValue.IsNullOrWhiteSpace())
            {
                throw new ArgumentNullException(nameof(idValue));
            }

            var idElement = base.GetIdElement(document, idValue);

            if (idElement != null)
            {
                return(idElement);
            }

            var nsManager = XmlConstants.GetXmlNamespaceManager(document);

            foreach (var idName in _idAttributeNames)
            {
                if (document.SelectSingleNode(
                        string.Format(CultureInfo.InvariantCulture, xmlIdXPathFormat, idName, idValue),
                        nsManager) is XmlElement element)
                {
                    return(element);
                }
            }

            return(null);
        }
예제 #2
0
        public virtual void Decrypt(
            XmlDocument document)
        {
            if (document == null)
            {
                throw new ArgumentNullException(nameof(document));
            }

            InitializeSymmetricKey();

            foreach (XmlElement element in document.SelectNodes(XmlConstants.XPathEncryptedElements, XmlConstants.GetEncryptNamespaceManager(document)))
            {
                DecryptElement(element);
            }
        }
예제 #3
0
        /// <summary>
        /// Gets the references.
        /// </summary>
        /// <param name="signedXml">The signed XML.</param>
        /// <param name="document">The document.</param>
        /// <param name="xmlPath">The XML path.</param>
        /// <param name="namespaceManager">The namespace manager.</param>
        /// <param name="documentLocation">The document location.</param>
        /// <returns>IEnumerable&lt;Reference&gt;.</returns>
        IEnumerable <Reference> GetReferences(
            SignedXml signedXml,
            XmlDocument document,
            string xmlPath,
            XmlNamespaceManager namespaceManager,
            Uri documentLocation)
        {
            XmlNodeList elements = null;

            if (SignatureLocation == SignatureLocation.Enveloping)
            {
                // ignore the path - it doesn't make sense - always sign the document's root element and import it into /Signature/Object
                xmlPath = _xPathRootElement;
            }

            if (xmlPath != null)
            {
                elements = document.SelectNodes(xmlPath, namespaceManager);

                if (elements.Count == 1 && elements[0] is XmlDocument)
                {
                    // the path points to the document node
                    elements = null;
                }
            }

            if (elements == null)
            {
                // sign the whole document
                var reference = new Reference();

                if (SignatureLocation == SignatureLocation.Enveloped)
                {
                    reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
                }

                if (SignatureLocation == SignatureLocation.Detached && documentLocation != null && !documentLocation.IsFile)
                {
                    reference.Uri = documentLocation.ToString();
                }
                else
                {
                    reference.Uri = "";
                }

                yield return(reference);
            }
            else
            {
                // build a set of all possible unique ID attribute names:
                var nameIds = new HashSet <string> {
                    "id", "Id", "ID"
                };                                                          // these are always here

                if (IdAttributeNames != null)
                {
                    nameIds.UnionWith(IdAttributeNames);    // add the custom ones
                }
                else
                {
                    nameIds.Add(XmlConstants.Id);           // add the XML standard one
                }
                var nsManager = XmlConstants.GetXmlNamespaceManager(document);

                // a set of all unique id-s in the document will help us generate new unique xml:Id-s
                var xmlIds = new HashSet <string>();

                foreach (var name in nameIds)
                {
                    xmlIds.UnionWith(
                        document.SelectNodes(
                            string.Format(CultureInfo.InvariantCulture, _xPathAllAttributes, name),
                            nsManager)
                        .OfType <XmlAttribute>()
                        .Select(a => a.Value)
                        .Distinct());
                }

                var id = 0;

                foreach (var element in elements.OfType <XmlElement>())
                {
                    string xmlId = null;

                    if (SignatureLocation == SignatureLocation.Enveloping)
                    {
                        // we need a new unique xml:Id for the Object element
                        xmlId = GetNewId(ref id, xmlIds);

                        // wrap the root element in a /Signature/Object element
                        signedXml.AddObject(
                            new DataObject
                        {
                            Data = elements,      // contains the root element only
                            Id   = xmlId,         // add the xml:Id to the object, so that we can refer to it from the reference object
                        });
                    }
                    else
                    {
                        // find a unique ID - any one of the set should do
                        foreach (var name in nameIds)
                        {
                            if (element.SelectSingleNode("@" + name, nsManager) is XmlAttribute attribute && attribute.Value != null)
                            {
                                xmlId = attribute.Value;
                                break;
                            }
                        }

                        // if it doesn't have unique id, generate a new one and add it to the element, so that we can refer to it from the reference object
                        if (string.IsNullOrWhiteSpace(xmlId))
                        {
                            xmlId = GetNewId(ref id, xmlIds);

                            var attribute = document.CreateAttribute(XmlConstants.Prefix, XmlConstants.IdLocalName, XmlConstants.Namespace);

                            attribute.Value = xmlId;
                            element.Attributes.Append(attribute);
                        }
                    }

                    // create the reference object
                    var reference = new Reference("#" + xmlId)
                    {
                        DigestMethod = _digestMethod
                    };

                    switch (HashAlgorithmName)
                    {
                    case Algorithms.Hash.Sha256:
                        reference.AddTransform(new XmlDsigExcC14NTransform());
                        break;

#pragma warning disable 0612, 0618 // Type or member is obsolete - used for bacwards compatibility
                    case Algorithms.Hash.Sha1:
                        reference.AddTransform(new XmlDsigC14NTransform());
                        break;
#pragma warning restore 0612, 0618 // Type or member is obsolete - used for bacwards compatibility
                    }

                    if (SignatureLocation == SignatureLocation.Enveloped)
                    {
                        reference.AddTransform(new XmlDsigEnvelopedSignatureTransform());
                    }

                    yield return(reference);
                }
            }
        }