internal static XmlNodeList AllDescendantNodes(XmlNode node, bool includeComments) { CanonicalXmlNodeList nodeList = new CanonicalXmlNodeList(); CanonicalXmlNodeList elementList = new CanonicalXmlNodeList(); CanonicalXmlNodeList attribList = new CanonicalXmlNodeList(); CanonicalXmlNodeList namespaceList = new CanonicalXmlNodeList(); int index = 0; elementList.Add(node); do { XmlNode rootNode = (XmlNode)elementList[index]; // Add the children nodes XmlNodeList childNodes = rootNode.ChildNodes; if (childNodes != null) { foreach (XmlNode node1 in childNodes) { if (includeComments || (!(node1 is XmlComment))) { elementList.Add(node1); } } } // Add the attribute nodes XmlAttributeCollection attribNodes = rootNode.Attributes; if (attribNodes != null) { foreach (XmlNode attribNode in rootNode.Attributes) { if (attribNode.LocalName == "xmlns" || attribNode.Prefix == "xmlns") { namespaceList.Add(attribNode); } else { attribList.Add(attribNode); } } } index++; } while (index < elementList.Count); foreach (XmlNode elementNode in elementList) { nodeList.Add(elementNode); } foreach (XmlNode attribNode in attribList) { nodeList.Add(attribNode); } foreach (XmlNode namespaceNode in namespaceList) { nodeList.Add(namespaceNode); } return(nodeList); }
public DataObject(string id, string mimeType, string encoding, XmlElement data) { if (data == null) { throw new ArgumentNullException("data"); } m_id = id; m_mimeType = mimeType; m_encoding = encoding; m_elData = new CanonicalXmlNodeList(); m_elData.Add(data); m_cachedXml = null; }
internal static void AddNamespaces(XmlElement elem, CanonicalXmlNodeList namespaces) { if (namespaces != null) { foreach (XmlNode attrib in namespaces) { string name = ((attrib.Prefix.Length > 0) ? attrib.Prefix + ":" + attrib.LocalName : attrib.LocalName); // Skip the attribute if one with the same qualified name already exists if (elem.HasAttribute(name) || (name.Equals("xmlns") && elem.Prefix.Length == 0)) { continue; } XmlAttribute nsattrib = (XmlAttribute)elem.OwnerDocument.CreateAttribute(name); nsattrib.Value = attrib.Value; elem.SetAttributeNode(nsattrib); } } }
protected void BuildDigestedReferences() { // Default the DigestMethod and Canonicalization ArrayList references = SignedInfo.References; // Reset the cache m_refProcessed = new bool[references.Count]; m_refLevelCache = new int[references.Count]; ReferenceLevelSortOrder sortOrder = new ReferenceLevelSortOrder(); sortOrder.References = references; // Don't alter the order of the references array list ArrayList sortedReferences = new ArrayList(); foreach (Reference reference in references) { sortedReferences.Add(reference); } sortedReferences.Sort(sortOrder); CanonicalXmlNodeList nodeList = new CanonicalXmlNodeList(); foreach (DataObject obj in m_signature.ObjectList) { nodeList.Add(obj.GetXml()); } foreach (Reference reference in sortedReferences) { // If no DigestMethod has yet been set, default it to sha1 if (reference.DigestMethod == null) { reference.DigestMethod = XmlDsigSHA1Url; } reference.UpdateHashValue(m_containingDocument, nodeList); // If this reference has an Id attribute, add it if (reference.Id != null) { nodeList.Add(reference.GetXml()); } } }
private static void MarkInclusionStateForNodes(XmlNodeList nodeList, XmlDocument inputRoot, XmlDocument root) { CanonicalXmlNodeList elementList = new CanonicalXmlNodeList(); CanonicalXmlNodeList elementListCanonical = new CanonicalXmlNodeList(); elementList.Add(inputRoot); elementListCanonical.Add(root); int index = 0; do { XmlNode currentNode = (XmlNode)elementList[index]; XmlNode currentNodeCanonical = (XmlNode)elementListCanonical[index]; XmlNodeList childNodes = currentNode.ChildNodes; XmlNodeList childNodesCanonical = currentNodeCanonical.ChildNodes; for (int i = 0; i < childNodes.Count; i++) { elementList.Add(childNodes[i]); elementListCanonical.Add(childNodesCanonical[i]); if (Utils.NodeInList(childNodes[i], nodeList)) { MarkNodeAsIncluded(childNodesCanonical[i]); } XmlAttributeCollection attribNodes = childNodes[i].Attributes; if (attribNodes != null) { for (int j = 0; j < attribNodes.Count; j++) { if (Utils.NodeInList(attribNodes[j], nodeList)) { MarkNodeAsIncluded(childNodesCanonical[i].Attributes.Item(j)); } } } } index++; } while (index < elementList.Count); }
// Allow machine admins to add additional canonicalization algorithms that should be considered valid when // validating XML signatuers by supplying a list in the // HKLM\Software\Microsoft\.NETFramework\Security\SafeCanonicalizationMethods // key. Each REG_SZ entry in this key will be considered a canonicalziation algorithm URI that should be // allowed by SignedXml instances on this machine. //[RegistryPermission(SecurityAction.Assert, Unrestricted = true)] //[SecuritySafeCritical] //private static List<string> ReadAdditionalSafeCanonicalizationMethods() { // List<string> additionalAlgorithms = new List<string>(); // try { // using (RegistryKey canonicalizationAlgorithmsKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\.NETFramework\Security\SafeCanonicalizationMethods", false)) { // if (canonicalizationAlgorithmsKey != null) { // foreach (string value in canonicalizationAlgorithmsKey.GetValueNames()) { // if (canonicalizationAlgorithmsKey.GetValueKind(value) == RegistryValueKind.String) { // string additionalAlgorithm = canonicalizationAlgorithmsKey.GetValue(value) as string; // if (!String.IsNullOrWhiteSpace(additionalAlgorithm)) { // additionalAlgorithms.Add(additionalAlgorithm); // } // } // } // } // } // } // catch (SecurityException) { /* we could not open the key - that's fine, we can proceed with no additional algorithms */ } // return additionalAlgorithms; //} private byte[] GetC14NDigest(HashAlgorithm hash) { if (!bCacheValid || !this.SignedInfo.CacheValid) { string baseUri = (m_containingDocument == null ? null : m_containingDocument.BaseURI); XmlResolver resolver = (m_bResolverSet ? m_xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); XmlDocument doc = Utils.PreProcessElementInput(SignedInfo.GetXml(), resolver, baseUri); // Add non default namespaces in scope CanonicalXmlNodeList namespaces = (m_context == null ? null : Utils.GetPropagatedAttributes(m_context)); Utils.AddNamespaces(doc.DocumentElement, namespaces); Transform c14nMethodTransform = SignedInfo.CanonicalizationMethodObject; c14nMethodTransform.Resolver = resolver; c14nMethodTransform.BaseURI = baseUri; c14nMethodTransform.LoadInput(doc); _digestedSignedInfo = c14nMethodTransform.GetDigestedOutput(hash); bCacheValid = true; } return(_digestedSignedInfo); }
// This method gets the attributes that should be propagated internal static CanonicalXmlNodeList GetPropagatedAttributes(XmlElement elem) { if (elem == null) { return(null); } CanonicalXmlNodeList namespaces = new CanonicalXmlNodeList(); XmlNode ancestorNode = elem; if (ancestorNode == null) { return(null); } bool bDefNamespaceToAdd = true; while (ancestorNode != null) { XmlElement ancestorElement = ancestorNode as XmlElement; if (ancestorElement == null) { ancestorNode = ancestorNode.ParentNode; continue; } if (!Utils.IsCommittedNamespace(ancestorElement, ancestorElement.Prefix, ancestorElement.NamespaceURI)) { // Add the namespace attribute to the collection if needed if (!Utils.IsRedundantNamespace(ancestorElement, ancestorElement.Prefix, ancestorElement.NamespaceURI)) { string name = ((ancestorElement.Prefix.Length > 0) ? "xmlns:" + ancestorElement.Prefix : "xmlns"); XmlAttribute nsattrib = elem.OwnerDocument.CreateAttribute(name); nsattrib.Value = ancestorElement.NamespaceURI; namespaces.Add(nsattrib); } } if (ancestorElement.HasAttributes) { XmlAttributeCollection attribs = ancestorElement.Attributes; foreach (XmlAttribute attrib in attribs) { // Add a default namespace if necessary if (bDefNamespaceToAdd && attrib.LocalName == "xmlns") { XmlAttribute nsattrib = elem.OwnerDocument.CreateAttribute("xmlns"); nsattrib.Value = attrib.Value; namespaces.Add(nsattrib); bDefNamespaceToAdd = false; continue; } // retain the declarations of type 'xml:*' as well if (attrib.Prefix == "xmlns" || attrib.Prefix == "xml") { namespaces.Add(attrib); continue; } if (attrib.NamespaceURI.Length > 0) { if (!Utils.IsCommittedNamespace(ancestorElement, attrib.Prefix, attrib.NamespaceURI)) { // Add the namespace attribute to the collection if needed if (!Utils.IsRedundantNamespace(ancestorElement, attrib.Prefix, attrib.NamespaceURI)) { string name = ((attrib.Prefix.Length > 0) ? "xmlns:" + attrib.Prefix : "xmlns"); XmlAttribute nsattrib = elem.OwnerDocument.CreateAttribute(name); nsattrib.Value = attrib.NamespaceURI; namespaces.Add(nsattrib); } } } } } ancestorNode = ancestorNode.ParentNode; } return(namespaces); }
internal byte[] CalculateHashValue(XmlDocument document, CanonicalXmlNodeList refList) { // refList is a list of elements that might be targets of references // Now's the time to create our hashing algorithm m_hashAlgorithm = GostCryptoConfig.CreateFromName(m_digestMethod) as HashAlgorithm; if (m_hashAlgorithm == null) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_CreateHashAlgorithmFailed")); } // Let's go get the target. string baseUri = (document == null ? System.Environment.CurrentDirectory + "\\" : document.BaseURI); Stream hashInputStream = null; WebRequest request = null; WebResponse response = null; Stream inputStream = null; XmlResolver resolver = null; byte[] hashval = null; try { switch (m_refTargetType) { case ReferenceTargetType.Stream: // This is the easiest case. We already have a stream, so just pump it through the TransformChain resolver = (this.SignedXml.ResolverSet ? this.SignedXml.m_xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); hashInputStream = this.TransformChain.TransformToOctetStream((Stream)m_refTarget, resolver, baseUri); break; case ReferenceTargetType.UriReference: // Second-easiest case -- dereference the URI & pump through the TransformChain // handle the special cases where the URI is null (meaning whole doc) // or the URI is just a fragment (meaning a reference to an embedded Object) if (m_uri == null) { // We need to create a DocumentNavigator out of the XmlElement resolver = (this.SignedXml.ResolverSet ? this.SignedXml.m_xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); // In the case of a Uri-less reference, we will simply pass null to the transform chain. // The first transform in the chain is expected to know how to retrieve the data to hash. hashInputStream = this.TransformChain.TransformToOctetStream((Stream)null, resolver, baseUri); } else if (m_uri.Length == 0) { // This is the self-referential case. First, check that we have a document context. // The Enveloped Signature does not discard comments as per spec; those will be omitted during the transform chain process if (document == null) { throw new CryptographicException(String.Format(CultureInfo.CurrentCulture, SecurityResources.GetResourceString("Cryptography_Xml_SelfReferenceRequiresContext"), m_uri)); } // Normalize the containing document resolver = (this.SignedXml.ResolverSet ? this.SignedXml.m_xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); XmlDocument docWithNoComments = Utils.DiscardComments(Utils.PreProcessDocumentInput(document, resolver, baseUri)); hashInputStream = this.TransformChain.TransformToOctetStream(docWithNoComments, resolver, baseUri); } else if (m_uri[0] == '#') { // If we get here, then we are constructing a Reference to an embedded DataObject // referenced by an Id = attribute. Go find the relevant object bool discardComments = true; string idref = Utils.GetIdFromLocalUri(m_uri, out discardComments); if (idref == "xpointer(/)") { // This is a self referencial case if (document == null) { throw new CryptographicException(String.Format(CultureInfo.CurrentCulture, SecurityResources.GetResourceString("Cryptography_Xml_SelfReferenceRequiresContext"), m_uri)); } // We should not discard comments here!!! resolver = (this.SignedXml.ResolverSet ? this.SignedXml.m_xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); hashInputStream = this.TransformChain.TransformToOctetStream(Utils.PreProcessDocumentInput(document, resolver, baseUri), resolver, baseUri); break; } XmlElement elem = this.SignedXml.GetIdElement(document, idref); if (elem != null) { m_namespaces = Utils.GetPropagatedAttributes(elem.ParentNode as XmlElement); } if (elem == null) { // Go throw the referenced items passed in if (refList != null) { foreach (XmlNode node in refList) { XmlElement tempElem = node as XmlElement; if ((tempElem != null) && (Utils.HasAttribute(tempElem, "Id", SignedXml.XmlDsigNamespaceUrl)) && (Utils.GetAttribute(tempElem, "Id", SignedXml.XmlDsigNamespaceUrl).Equals(idref))) { elem = tempElem; if (this.m_signedXml.m_context != null) { m_namespaces = Utils.GetPropagatedAttributes(this.m_signedXml.m_context); } break; } } } } if (elem == null) { throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_InvalidReference")); } XmlDocument normDocument = Utils.PreProcessElementInput(elem, resolver, baseUri); // Add the propagated attributes Utils.AddNamespaces(normDocument.DocumentElement, m_namespaces); resolver = (this.SignedXml.ResolverSet ? this.SignedXml.m_xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); if (discardComments) { // We should discard comments before going into the transform chain XmlDocument docWithNoComments = Utils.DiscardComments(normDocument); hashInputStream = this.TransformChain.TransformToOctetStream(docWithNoComments, resolver, baseUri); } else { // This is an XPointer reference, do not discard comments!!! hashInputStream = this.TransformChain.TransformToOctetStream(normDocument, resolver, baseUri); } } else { // WebRequest always expects an Absolute Uri, so try to resolve if we were passed a relative Uri. System.Uri uri = new System.Uri(m_uri, UriKind.RelativeOrAbsolute); if (!uri.IsAbsoluteUri) { uri = new Uri(new Uri(baseUri), uri); } request = WebRequest.Create(uri); if (request == null) { goto default; } response = request.GetResponse(); if (response == null) { goto default; } inputStream = response.GetResponseStream(); if (inputStream == null) { goto default; } resolver = (this.SignedXml.ResolverSet ? this.SignedXml.m_xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); hashInputStream = this.TransformChain.TransformToOctetStream(inputStream, resolver, m_uri); } break; case ReferenceTargetType.XmlElement: // We need to create a DocumentNavigator out of the XmlElement resolver = (this.SignedXml.ResolverSet ? this.SignedXml.m_xmlResolver : new XmlSecureResolver(new XmlUrlResolver(), baseUri)); hashInputStream = this.TransformChain.TransformToOctetStream(Utils.PreProcessElementInput((XmlElement)m_refTarget, resolver, baseUri), resolver, baseUri); break; default: throw new CryptographicException(SecurityResources.GetResourceString("Cryptography_Xml_UriNotResolved"), m_uri); } // Compute the new hash value //hashInputStream = SignedXmlDebugLog.LogReferenceData(this, hashInputStream); hashval = m_hashAlgorithm.ComputeHash(hashInputStream); } finally { if (hashInputStream != null) { hashInputStream.Close(); } if (response != null) { response.Close(); } if (inputStream != null) { inputStream.Close(); } } return(hashval); }
internal void UpdateHashValue(XmlDocument document, CanonicalXmlNodeList refList) { DigestValue = CalculateHashValue(document, refList); }
// // public constructors // public Signature() { m_embeddedObjects = new ArrayList(); m_referencedItems = new CanonicalXmlNodeList(); }
// // public constructors // public DataObject() { m_cachedXml = null; m_elData = new CanonicalXmlNodeList(); }