Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Base / MS / Internal / IO / Packaging / XmlSignatureManifest.cs / 1305600 / XmlSignatureManifest.cs
//------------------------------------------------------------------------------ // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // Signature processor implementation that follows the Feb 12, 2002 W3C DigSig Recommendation // // Generates and consumes Manifest portion of the // XmlDSig-compliant digital signatures based on the subset // specified by the OPC file format. // // Manifest appears in this context: // // // // Manifest form is: // //// // # simple reference - no transforms // // History: // 01/25/2004: BruceMac: Initial Implementation // //----------------------------------------------------------------------------- using System; using System.Diagnostics; using System.Collections; using System.Collections.Generic; //using System.Security; // for SecurityCritical and SecurityTreatAsSafe using System.Security.Cryptography; using System.Security.Cryptography.Xml; using System.Security.Cryptography.X509Certificates; using System.Xml; using System.IO; using System.Windows; using System.IO.Packaging; using MS.Internal; using MS.Internal.WindowsBase; namespace MS.Internal.IO.Packaging { ///// // // # simple reference with c14n canonicalization transform //// ... //// // // # reference that signs multiple PackageRelationships //// //// // ... //// // // # reference that signs PackageRelationships by Relationship Type and a single Relationship by ID //// //// //// // // // // ... //// // ... // //// //// //// // // // ... ///// Manifest generator/parser /// ///See: http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/ for details internal static class XmlSignatureManifest { //----------------------------------------------------- // // Internal Methods // //----------------------------------------------------- ////// Parse the Manifest tag /// /// /// XmlReader positioned to the Manifest tag /// /// /// internal static void ParseManifest( PackageDigitalSignatureManager manager, XmlReader reader, out ListpartManifest, out List partEntryManifest, out List relationshipManifest) { Invariant.Assert(manager != null); Invariant.Assert(reader != null); // these are empty (non-null) when nothing is found partManifest = new List (); partEntryManifest = new List (); relationshipManifest = new List (); // manually parse the Relationship tags because they are custom formed and the Reference class will not handle // them correctly string referenceTagName = XTable.Get(XTable.ID.ReferenceTagName); int referenceCount = 0; while (reader.Read() && (reader.MoveToContent() == XmlNodeType.Element)) { // should be on a tag if (String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) == 0 && (String.CompareOrdinal(reader.LocalName, referenceTagName) == 0) && reader.Depth == 2) { // Parse each reference - distinguish between Relationships and Parts // because we don't store the Relationship-part itself - just it's Relationships. PartManifestEntry partManifestEntry = ParseReference(reader); if (partManifestEntry.IsRelationshipEntry) { foreach (PackageRelationshipSelector relationshipSelector in partManifestEntry.RelationshipSelectors) relationshipManifest.Add(relationshipSelector); } else partManifest.Add(partManifestEntry.Uri); // return the manifest entry to be used for hashing partEntryManifest.Add(partManifestEntry); referenceCount++; } else throw new XmlException(SR.Get(SRID.UnexpectedXmlTag, reader.Name)); } // XmlDSig xsd requires at least one tag if (referenceCount == 0) throw new XmlException(SR.Get(SRID.PackageSignatureCorruption)); } /// /// Parse the DigestMethod tag /// /// private static string ParseDigestAlgorithmTag(XmlReader reader) { // verify namespace and lack of attributes if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) > 1 || String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) != 0 || reader.Depth != 3) throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); // get the Algorithm attribute string hashAlgorithm = null; if (reader.HasAttributes) { hashAlgorithm = reader.GetAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); } if (hashAlgorithm == null || hashAlgorithm.Length == 0) throw new XmlException(SR.Get(SRID.UnsupportedHashAlgorithm)); return hashAlgorithm; } ////// Parse the DigestValue tag /// /// private static string ParseDigestValueTag(XmlReader reader) { Debug.Assert(reader != null); // verify namespace and lack of attributes if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) > 0 || String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) != 0 || reader.Depth != 3) throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); // there are no legal attributes and the only content must be text if (reader.HasAttributes || (reader.Read() && reader.MoveToContent() != XmlNodeType.Text)) throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); // get the Value return reader.ReadString(); } ////// Get the part uri and it's content type from the current Reference tag /// /// /// contentType extracted from the query portion of the Uri ///PackagePart uri and contentType private static Uri ParsePartUri(XmlReader reader, out ContentType contentType) { // should be a relative Package uri with a query portion that contains the ContentType contentType = ContentType.Empty; Uri partUri = null; // must be one and only one attribute if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) == 1) { string uriAttrValue = reader.GetAttribute(XTable.Get(XTable.ID.UriAttrName)); if (uriAttrValue != null) { partUri = ParsePartUriAttribute(uriAttrValue, out contentType); } } // will be null if we had no success if (partUri == null) throw new XmlException(SR.Get(SRID.RequiredXmlAttributeMissing, XTable.Get(XTable.ID.UriAttrName))); return partUri; } ////// Parses a Reference tag /// /// ///partManifestEntry that represents the state of the tag private static PartManifestEntry ParseReference(XmlReader reader) { Debug.Assert(reader != null); //found - get part Uri from the tag ContentType contentType = null; Uri partUri = ParsePartUri(reader, out contentType); // only allocate if this turns out to be a Relationship transform List relationshipSelectors = null; // move through the sub-tags: , and optional string hashAlgorithm = null; // digest method string hashValue = null; // digest value List transforms = null; // optional transform algorithm names bool transformsParsed = false; // since null is legal for transforms var we need a // bool to detect multiples while (reader.Read() && (reader.MoveToContent() == XmlNodeType.Element)) { // Correct Namespace? if (String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) != 0 || reader.Depth != 3) { throw new XmlException(SR.Get(SRID.PackageSignatureCorruption)); } // DigestMethod? if (hashAlgorithm == null && String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.DigestMethodTagName)) == 0) { hashAlgorithm = ParseDigestAlgorithmTag(reader); continue; } // DigestValue? if (hashValue == null && String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.DigestValueTagName)) == 0) { hashValue = ParseDigestValueTag(reader); continue; } // TransformsTag? if (!transformsParsed && String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.TransformsTagName)) == 0) { transforms = ParseTransformsTag(reader, partUri, ref relationshipSelectors); transformsParsed = true; continue; } // if we get to here, we didn't see what we expected throw new XmlException(SR.Get(SRID.PackageSignatureCorruption)); } // add to our list return new PartManifestEntry(partUri, contentType, hashAlgorithm, hashValue, transforms, relationshipSelectors); } /// /// Parses Transforms tag /// /// node to parse /// Part Uri for the part owning the relationships /// allocates and returns a list of /// PackageRelationshipSelectors if Relationship transform ///ordered list of Transform names private static ListParseTransformsTag(XmlReader reader, Uri partUri, ref List relationshipSelectors) { // # reference that signs multiple PackageRelationships // // // verify lack of attributes if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) != 0) throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); List// //// //// // // // // ... //transforms = null; bool relationshipTransformFound = false; int transformsCountWhenRelationshipTransformFound = 0; // Look for transforms. // There are currently only 3 legal transforms which can be arranged in any // combination. while (reader.Read() && (reader.MoveToContent() == XmlNodeType.Element)) { String transformName = null; // at this level, all tags must be Transform tags if (reader.Depth != 4 || String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) != 0 || String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.TransformTagName)) != 0) { throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); } // inspect the Algorithm attribute to determine the type of transform if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) == 1) { transformName = reader.GetAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); } // legal transform name? if ((transformName != null) && (transformName.Length > 0)) { // what type of transform? if (String.CompareOrdinal(transformName, XTable.Get(XTable.ID.RelationshipsTransformName)) == 0) { if (!relationshipTransformFound) { // relationship transform ParseRelationshipsTransform(reader, partUri, ref relationshipSelectors); if (transforms == null) transforms = new List (); transforms.Add(transformName); relationshipTransformFound = true; transformsCountWhenRelationshipTransformFound = transforms.Count; continue; // success } else throw new XmlException(SR.Get(SRID.MultipleRelationshipTransformsFound)); } else { // non-Relationship transform should have no children if (reader.IsEmptyElement) { if (transforms == null) transforms = new List (); if (XmlDigitalSignatureProcessor.IsValidXmlCanonicalizationTransform(transformName)) { transforms.Add(transformName); // return it continue; // success } else throw new InvalidOperationException(SR.Get(SRID.UnsupportedTransformAlgorithm)); } } } throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); } if (transforms.Count == 0) throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); //If we found another transform after the Relationship transform, it will be validated earlier //in this method to make sure that its a supported xml canonicalization algorithm and so we can //simplify this test condition - As per the OPC spec - Relationship transform must be followed //by a canonicalization algorithm. if (relationshipTransformFound && (transforms.Count == transformsCountWhenRelationshipTransformFound)) throw new XmlException(SR.Get(SRID.RelationshipTransformNotFollowedByCanonicalizationTransform)); return transforms; } /// /// Parse the Relationship-specific Transform /// /// /// /// may be allocated but will never be empty private static void ParseRelationshipsTransform(XmlReader reader, Uri partUri, ref ListrelationshipSelectors) { Uri owningPartUri = PackUriHelper.GetSourcePartUriFromRelationshipPartUri(partUri); // find all of the Relationship tags of form: // // or // while (reader.Read() && (reader.MoveToContent() == XmlNodeType.Element) && reader.Depth == 5) { // both types have no children, a single required attribute and belong to the OPC namespace if (reader.IsEmptyElement && PackagingUtilities.GetNonXmlnsAttributeCount(reader) == 1 && (String.CompareOrdinal(reader.NamespaceURI, XTable.Get(XTable.ID.OpcSignatureNamespace)) == 0)) { // ? if (String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.RelationshipReferenceTagName)) == 0) { // RelationshipReference tags are legal and these must be empty with a single SourceId attribute // get the SourceId attribute string id = reader.GetAttribute(XTable.Get(XTable.ID.SourceIdAttrName)); if (id != null && id.Length > 0) { if (relationshipSelectors == null) relationshipSelectors = new List (); // we found a legal SourceId so create a selector and continue searching relationshipSelectors.Add(new PackageRelationshipSelector(owningPartUri, PackageRelationshipSelectorType.Id, id)); continue; } } // ? else if ((String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.RelationshipsGroupReferenceTagName)) == 0)) { // RelationshipsGroupReference tags must be empty with a single SourceType attribute string type = reader.GetAttribute(XTable.Get(XTable.ID.SourceTypeAttrName)); if (type != null && type.Length > 0) { // lazy init if (relationshipSelectors == null) relationshipSelectors = new List (); // got a legal SourceType attribute relationshipSelectors.Add(new PackageRelationshipSelector(owningPartUri, PackageRelationshipSelectorType.Type, type)); continue; } } } // if we get to here, we have not found a legal tag so we throw throw new XmlException(SR.Get(SRID.UnexpectedXmlTag, reader.LocalName)); } } /// /// Generate Manifest tag /// /// manager /// current Xml doc /// hash algorithm to hash with /// parts to sign - possibly null /// relationshipSelectors that represent the /// relationships that have to be signed - possibly null ///internal static XmlNode GenerateManifest( PackageDigitalSignatureManager manager, XmlDocument xDoc, HashAlgorithm hashAlgorithm, IEnumerable parts, IEnumerable relationshipSelectors) { Debug.Assert(manager != null); Debug.Assert(xDoc != null); Debug.Assert(hashAlgorithm != null); // check args if (!hashAlgorithm.CanReuseTransform) throw new ArgumentException(SR.Get(SRID.HashAlgorithmMustBeReusable)); // XmlNode manifest = xDoc.CreateNode(XmlNodeType.Element, XTable.Get(XTable.ID.ManifestTagName), SignedXml.XmlDsigNamespaceUrl); // add part references if (parts != null) { // loop and write - may still be empty foreach (Uri partUri in parts) { // generate a reference tag manifest.AppendChild(GeneratePartSigningReference(manager, xDoc, hashAlgorithm, partUri)); } } // any relationship references? int relationshipCount = 0; if (relationshipSelectors != null) { relationshipCount = GenerateRelationshipSigningReferences(manager, xDoc, hashAlgorithm, relationshipSelectors, manifest); } // did we sign anything? Manifest can NOT be empty if (parts == null && relationshipCount == 0) throw new ArgumentException(SR.Get(SRID.NothingToSign)); return manifest; } //------------------------------------------------------ // // Private Methods // //----------------------------------------------------- /// /// GenerateRelationshipSigningReferences /// /// /// /// /// /// ///number of references to be signed private static int GenerateRelationshipSigningReferences( PackageDigitalSignatureManager manager, XmlDocument xDoc, HashAlgorithm hashAlgorithm, IEnumerablerelationshipSelectors, XmlNode manifest) { // PartUri - and its list of PackageRelationshipSelectors Dictionary > partAndSelectorDictionary = new Dictionary >(); foreach (PackageRelationshipSelector relationshipSelector in relationshipSelectors) { //update the partAndSelectorDictionary for each relationshipSelector Uri relationshipPartUri = PackUriHelper.GetRelationshipPartUri(relationshipSelector.SourceUri); List selectors; if (partAndSelectorDictionary.ContainsKey(relationshipPartUri)) selectors = partAndSelectorDictionary[relationshipPartUri]; else { selectors = new List (); partAndSelectorDictionary.Add(relationshipPartUri, selectors); } selectors.Add(relationshipSelector); } // now that we have them grouped by Part name, emit the XML // Here is an optimization for saving space by declaring the OPC namespace and prefix // in the tag. It will become: // // Later when we generate the RelationshipSigningReference we can use the namespace prefix "opc" // instead of the long namespace itself, thus saving some space if the manifest has more than one // RelationshipSigningReference. // XmlElement xmlE = (XmlElement)manifest; xmlE.SetAttribute(XTable.Get(XTable.ID.OpcSignatureNamespaceAttribute), XTable.Get(XTable.ID.OpcSignatureNamespace)); int count = 0; foreach (Uri partName in partAndSelectorDictionary.Keys) { // emit xml and append manifest.AppendChild( GenerateRelationshipSigningReference(manager, xDoc, hashAlgorithm, partName, /* we are guaranteed that this is a valid part Uri, so we do not use PackUriHelper.CreatePartUri */ partAndSelectorDictionary[partName])); count++; } return count; } private static Uri ParsePartUriAttribute(String attrValue, out ContentType contentType) { // extract the query portion - do not ask the Uri class for it because it will escape // characters and we want to do a simple text comparison later contentType = ContentType.Empty; // out argument must always be set int index = attrValue.IndexOf('?'); Uri uri = null; if (index > 0) { try { // ensure it starts with the correct query prefix String query = attrValue.Substring(index); if ((query.Length > _contentTypeQueryStringPrefix.Length) && (query.StartsWith(_contentTypeQueryStringPrefix, StringComparison.Ordinal))) { // truncate the prefix and validate contentType = new ContentType(query.Substring(_contentTypeQueryStringPrefix.Length)); } // now construct the uri without the query uri = PackUriHelper.ValidatePartUri(new Uri(attrValue.Substring(0, index), UriKind.Relative)); } catch (ArgumentException ae) { // Content type or part uri is malformed so we have a bad signature. // Rethrow as XmlException so outer validation loop can catch it and return validation result. throw new XmlException(SR.Get(SRID.PartReferenceUriMalformed), ae); } } // throw if we failed if (contentType.ToString().Length <= 0) throw new XmlException(SR.Get(SRID.PartReferenceUriMalformed)); return uri; } /// /// Generates a Reference tag that contains a Relationship transform /// /// manager /// name of the relationship part /// current xml document /// hash algorithm = digest method /// relationshipSelectors that represent the relationships to sign ///ContentType is known and part name can be derived from the relationship collection private static XmlNode GenerateRelationshipSigningReference( PackageDigitalSignatureManager manager, XmlDocument xDoc, HashAlgorithm hashAlgorithm, Uri relationshipPartName, IEnumerablerelationshipSelectors) { string relPartContentType = PackagingUtilities.RelationshipPartContentType.ToString(); // XmlElement reference = xDoc.CreateElement(XTable.Get(XTable.ID.ReferenceTagName), SignedXml.XmlDsigNamespaceUrl); // add Uri // persist the Uri of the associated Relationship part String relationshipPartString; if (PackUriHelper.ComparePartUri(relationshipPartName, PackageRelationship.ContainerRelationshipPartName) == 0) relationshipPartString = PackageRelationship.ContainerRelationshipPartName.ToString(); else relationshipPartString = PackUriHelper.GetStringForPartUri(relationshipPartName); XmlAttribute uriAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.UriAttrName)); uriAttr.Value = relationshipPartString + _contentTypeQueryStringPrefix + relPartContentType; reference.Attributes.Append(uriAttr); // add transforms tag (always necessary) // XmlElement transforms = xDoc.CreateElement(XTable.Get(XTable.ID.TransformsTagName), SignedXml.XmlDsigNamespaceUrl); // add Relationship transform String opcNamespace = XTable.Get(XTable.ID.OpcSignatureNamespace); String opcNamespacePrefix = XTable.Get(XTable.ID.OpcSignatureNamespacePrefix); XmlElement transform = xDoc.CreateElement(XTable.Get(XTable.ID.TransformTagName), SignedXml.XmlDsigNamespaceUrl); XmlAttribute algorithmAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); algorithmAttr.Value = XTable.Get(XTable.ID.RelationshipsTransformName); transform.Attributes.Append(algorithmAttr); // or // foreach (PackageRelationshipSelector relationshipSelector in relationshipSelectors) { switch (relationshipSelector.SelectorType) { case PackageRelationshipSelectorType.Id: { XmlNode relationshipNode = xDoc.CreateElement(opcNamespacePrefix, XTable.Get(XTable.ID.RelationshipReferenceTagName), opcNamespace); XmlAttribute idAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.SourceIdAttrName)); idAttr.Value = relationshipSelector.SelectionCriteria; relationshipNode.Attributes.Append(idAttr); transform.AppendChild(relationshipNode); } break; case PackageRelationshipSelectorType.Type: { XmlNode relationshipNode = xDoc.CreateElement(opcNamespacePrefix, XTable.Get(XTable.ID.RelationshipsGroupReferenceTagName), opcNamespace); XmlAttribute typeAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.SourceTypeAttrName)); typeAttr.Value = relationshipSelector.SelectionCriteria; relationshipNode.Attributes.Append(typeAttr); transform.AppendChild(relationshipNode); } break; default: Invariant.Assert(false, "This option should never be executed"); break; } } transforms.AppendChild(transform); // add non-Relationship transform (if any) String transformName = null; if (manager.TransformMapping.ContainsKey(relPartContentType)) { transformName = manager.TransformMapping[relPartContentType]; // let them override //Currently we only support two transforms and so we validate whether its //one of those if (transformName == null || transformName.Length == 0 || !XmlDigitalSignatureProcessor.IsValidXmlCanonicalizationTransform(transformName)) throw new InvalidOperationException(SR.Get(SRID.UnsupportedTransformAlgorithm)); // transform = xDoc.CreateElement(XTable.Get(XTable.ID.TransformTagName), SignedXml.XmlDsigNamespaceUrl); algorithmAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); algorithmAttr.Value = transformName; transform.Attributes.Append(algorithmAttr); transforms.AppendChild(transform); } reference.AppendChild(transforms); // reference.AppendChild(GenerateDigestMethod(manager, xDoc)); // - digest the virtual node list made from these Relationship tags using (Stream s = XmlDigitalSignatureProcessor.GenerateRelationshipNodeStream(GetRelationships(manager, relationshipSelectors))) // serialized node list { reference.AppendChild(GenerateDigestValueNode(xDoc, hashAlgorithm, s, transformName)); } return reference; } private static XmlNode GeneratePartSigningReference( PackageDigitalSignatureManager manager, XmlDocument xDoc, HashAlgorithm hashAlgorithm, Uri partName) { PackagePart part = manager.Package.GetPart(partName); // XmlElement reference = xDoc.CreateElement(XTable.Get(XTable.ID.ReferenceTagName), SignedXml.XmlDsigNamespaceUrl); // add Uri with content type as Query XmlAttribute uriAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.UriAttrName)); uriAttr.Value = PackUriHelper.GetStringForPartUri(partName) + _contentTypeQueryStringPrefix + part.ContentType; reference.Attributes.Append(uriAttr); // add transforms tag if necessary String transformName = String.Empty; if (manager.TransformMapping.ContainsKey(part.ContentType)) { transformName = manager.TransformMapping[part.ContentType]; // XmlElement transforms = xDoc.CreateElement(XTable.Get(XTable.ID.TransformsTagName), SignedXml.XmlDsigNamespaceUrl); // XmlElement transform = xDoc.CreateElement(XTable.Get(XTable.ID.TransformTagName), SignedXml.XmlDsigNamespaceUrl); XmlAttribute algorithmAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); algorithmAttr.Value = transformName; transform.Attributes.Append(algorithmAttr); transforms.AppendChild(transform); reference.AppendChild(transforms); } // reference.AppendChild(GenerateDigestMethod(manager, xDoc)); // using (Stream s = part.GetStream(FileMode.Open, FileAccess.Read)) { reference.AppendChild(GenerateDigestValueNode(xDoc, hashAlgorithm, s, transformName)); } return reference; } private static XmlNode GenerateDigestMethod( PackageDigitalSignatureManager manager, XmlDocument xDoc) { // XmlElement digestMethod = xDoc.CreateElement(XTable.Get(XTable.ID.DigestMethodTagName), SignedXml.XmlDsigNamespaceUrl); XmlAttribute digestAlgorithmAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); digestAlgorithmAttr.Value = manager.HashAlgorithm; digestMethod.Attributes.Append(digestAlgorithmAttr); return digestMethod; } private static XmlNode GenerateDigestValueNode(XmlDocument xDoc, HashAlgorithm hashAlgorithm, Stream s, String transformName) { // XmlElement digestValue = xDoc.CreateElement(XTable.Get(XTable.ID.DigestValueTagName), SignedXml.XmlDsigNamespaceUrl); XmlText digestValueText = xDoc.CreateTextNode(XmlDigitalSignatureProcessor.GenerateDigestValue(s, transformName, hashAlgorithm)); digestValue.AppendChild(digestValueText); return digestValue; } //Returns the sorted PackageRelationship collection from a given collection of PackageRelationshipSelectors //Note: All the selectors in the given selector collection are assumed to be for the same Part/PackageRoot //This method should be called for a part/packageroot private static IEnumerable GetRelationships( PackageDigitalSignatureManager manager, IEnumerable relationshipSelectorsWithSameSource) { SortedDictionary relationshipsDictionarySortedById = new SortedDictionary (StringComparer.Ordinal); foreach (PackageRelationshipSelector relationshipSelector in relationshipSelectorsWithSameSource) { // loop and accumulate and group them by owning Part foreach (PackageRelationship r in relationshipSelector.Select(manager.Package)) { // add relationship if(!relationshipsDictionarySortedById.ContainsKey(r.Id)) relationshipsDictionarySortedById.Add(r.Id, r); } } return relationshipsDictionarySortedById.Values; } //------------------------------------------------------ // // Private Members // //------------------------------------------------------ const string _contentTypeQueryStringPrefix = "?ContentType="; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------------------------ // // // Copyright (C) Microsoft Corporation. All rights reserved. // // // Description: // Signature processor implementation that follows the Feb 12, 2002 W3C DigSig Recommendation // // Generates and consumes Manifest portion of the // XmlDSig-compliant digital signatures based on the subset // specified by the OPC file format. // // Manifest appears in this context: // // // // Manifest form is: // //// // # simple reference - no transforms // // History: // 01/25/2004: BruceMac: Initial Implementation // //----------------------------------------------------------------------------- using System; using System.Diagnostics; using System.Collections; using System.Collections.Generic; //using System.Security; // for SecurityCritical and SecurityTreatAsSafe using System.Security.Cryptography; using System.Security.Cryptography.Xml; using System.Security.Cryptography.X509Certificates; using System.Xml; using System.IO; using System.Windows; using System.IO.Packaging; using MS.Internal; using MS.Internal.WindowsBase; namespace MS.Internal.IO.Packaging { ///// // // # simple reference with c14n canonicalization transform //// ... //// // // # reference that signs multiple PackageRelationships //// //// // ... //// // // # reference that signs PackageRelationships by Relationship Type and a single Relationship by ID //// //// //// // // // // ... //// // ... // //// //// //// // // // ... ///// Manifest generator/parser /// ///See: http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/ for details internal static class XmlSignatureManifest { //----------------------------------------------------- // // Internal Methods // //----------------------------------------------------- ////// Parse the Manifest tag /// /// /// XmlReader positioned to the Manifest tag /// /// /// internal static void ParseManifest( PackageDigitalSignatureManager manager, XmlReader reader, out ListpartManifest, out List partEntryManifest, out List relationshipManifest) { Invariant.Assert(manager != null); Invariant.Assert(reader != null); // these are empty (non-null) when nothing is found partManifest = new List (); partEntryManifest = new List (); relationshipManifest = new List (); // manually parse the Relationship tags because they are custom formed and the Reference class will not handle // them correctly string referenceTagName = XTable.Get(XTable.ID.ReferenceTagName); int referenceCount = 0; while (reader.Read() && (reader.MoveToContent() == XmlNodeType.Element)) { // should be on a tag if (String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) == 0 && (String.CompareOrdinal(reader.LocalName, referenceTagName) == 0) && reader.Depth == 2) { // Parse each reference - distinguish between Relationships and Parts // because we don't store the Relationship-part itself - just it's Relationships. PartManifestEntry partManifestEntry = ParseReference(reader); if (partManifestEntry.IsRelationshipEntry) { foreach (PackageRelationshipSelector relationshipSelector in partManifestEntry.RelationshipSelectors) relationshipManifest.Add(relationshipSelector); } else partManifest.Add(partManifestEntry.Uri); // return the manifest entry to be used for hashing partEntryManifest.Add(partManifestEntry); referenceCount++; } else throw new XmlException(SR.Get(SRID.UnexpectedXmlTag, reader.Name)); } // XmlDSig xsd requires at least one tag if (referenceCount == 0) throw new XmlException(SR.Get(SRID.PackageSignatureCorruption)); } /// /// Parse the DigestMethod tag /// /// private static string ParseDigestAlgorithmTag(XmlReader reader) { // verify namespace and lack of attributes if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) > 1 || String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) != 0 || reader.Depth != 3) throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); // get the Algorithm attribute string hashAlgorithm = null; if (reader.HasAttributes) { hashAlgorithm = reader.GetAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); } if (hashAlgorithm == null || hashAlgorithm.Length == 0) throw new XmlException(SR.Get(SRID.UnsupportedHashAlgorithm)); return hashAlgorithm; } ////// Parse the DigestValue tag /// /// private static string ParseDigestValueTag(XmlReader reader) { Debug.Assert(reader != null); // verify namespace and lack of attributes if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) > 0 || String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) != 0 || reader.Depth != 3) throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); // there are no legal attributes and the only content must be text if (reader.HasAttributes || (reader.Read() && reader.MoveToContent() != XmlNodeType.Text)) throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); // get the Value return reader.ReadString(); } ////// Get the part uri and it's content type from the current Reference tag /// /// /// contentType extracted from the query portion of the Uri ///PackagePart uri and contentType private static Uri ParsePartUri(XmlReader reader, out ContentType contentType) { // should be a relative Package uri with a query portion that contains the ContentType contentType = ContentType.Empty; Uri partUri = null; // must be one and only one attribute if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) == 1) { string uriAttrValue = reader.GetAttribute(XTable.Get(XTable.ID.UriAttrName)); if (uriAttrValue != null) { partUri = ParsePartUriAttribute(uriAttrValue, out contentType); } } // will be null if we had no success if (partUri == null) throw new XmlException(SR.Get(SRID.RequiredXmlAttributeMissing, XTable.Get(XTable.ID.UriAttrName))); return partUri; } ////// Parses a Reference tag /// /// ///partManifestEntry that represents the state of the tag private static PartManifestEntry ParseReference(XmlReader reader) { Debug.Assert(reader != null); //found - get part Uri from the tag ContentType contentType = null; Uri partUri = ParsePartUri(reader, out contentType); // only allocate if this turns out to be a Relationship transform List relationshipSelectors = null; // move through the sub-tags: , and optional string hashAlgorithm = null; // digest method string hashValue = null; // digest value List transforms = null; // optional transform algorithm names bool transformsParsed = false; // since null is legal for transforms var we need a // bool to detect multiples while (reader.Read() && (reader.MoveToContent() == XmlNodeType.Element)) { // Correct Namespace? if (String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) != 0 || reader.Depth != 3) { throw new XmlException(SR.Get(SRID.PackageSignatureCorruption)); } // DigestMethod? if (hashAlgorithm == null && String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.DigestMethodTagName)) == 0) { hashAlgorithm = ParseDigestAlgorithmTag(reader); continue; } // DigestValue? if (hashValue == null && String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.DigestValueTagName)) == 0) { hashValue = ParseDigestValueTag(reader); continue; } // TransformsTag? if (!transformsParsed && String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.TransformsTagName)) == 0) { transforms = ParseTransformsTag(reader, partUri, ref relationshipSelectors); transformsParsed = true; continue; } // if we get to here, we didn't see what we expected throw new XmlException(SR.Get(SRID.PackageSignatureCorruption)); } // add to our list return new PartManifestEntry(partUri, contentType, hashAlgorithm, hashValue, transforms, relationshipSelectors); } /// /// Parses Transforms tag /// /// node to parse /// Part Uri for the part owning the relationships /// allocates and returns a list of /// PackageRelationshipSelectors if Relationship transform ///ordered list of Transform names private static ListParseTransformsTag(XmlReader reader, Uri partUri, ref List relationshipSelectors) { // # reference that signs multiple PackageRelationships // // // verify lack of attributes if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) != 0) throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); List// //// //// // // // // ... //transforms = null; bool relationshipTransformFound = false; int transformsCountWhenRelationshipTransformFound = 0; // Look for transforms. // There are currently only 3 legal transforms which can be arranged in any // combination. while (reader.Read() && (reader.MoveToContent() == XmlNodeType.Element)) { String transformName = null; // at this level, all tags must be Transform tags if (reader.Depth != 4 || String.CompareOrdinal(reader.NamespaceURI, SignedXml.XmlDsigNamespaceUrl) != 0 || String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.TransformTagName)) != 0) { throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); } // inspect the Algorithm attribute to determine the type of transform if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) == 1) { transformName = reader.GetAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); } // legal transform name? if ((transformName != null) && (transformName.Length > 0)) { // what type of transform? if (String.CompareOrdinal(transformName, XTable.Get(XTable.ID.RelationshipsTransformName)) == 0) { if (!relationshipTransformFound) { // relationship transform ParseRelationshipsTransform(reader, partUri, ref relationshipSelectors); if (transforms == null) transforms = new List (); transforms.Add(transformName); relationshipTransformFound = true; transformsCountWhenRelationshipTransformFound = transforms.Count; continue; // success } else throw new XmlException(SR.Get(SRID.MultipleRelationshipTransformsFound)); } else { // non-Relationship transform should have no children if (reader.IsEmptyElement) { if (transforms == null) transforms = new List (); if (XmlDigitalSignatureProcessor.IsValidXmlCanonicalizationTransform(transformName)) { transforms.Add(transformName); // return it continue; // success } else throw new InvalidOperationException(SR.Get(SRID.UnsupportedTransformAlgorithm)); } } } throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); } if (transforms.Count == 0) throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); //If we found another transform after the Relationship transform, it will be validated earlier //in this method to make sure that its a supported xml canonicalization algorithm and so we can //simplify this test condition - As per the OPC spec - Relationship transform must be followed //by a canonicalization algorithm. if (relationshipTransformFound && (transforms.Count == transformsCountWhenRelationshipTransformFound)) throw new XmlException(SR.Get(SRID.RelationshipTransformNotFollowedByCanonicalizationTransform)); return transforms; } /// /// Parse the Relationship-specific Transform /// /// /// /// may be allocated but will never be empty private static void ParseRelationshipsTransform(XmlReader reader, Uri partUri, ref ListrelationshipSelectors) { Uri owningPartUri = PackUriHelper.GetSourcePartUriFromRelationshipPartUri(partUri); // find all of the Relationship tags of form: // // or // while (reader.Read() && (reader.MoveToContent() == XmlNodeType.Element) && reader.Depth == 5) { // both types have no children, a single required attribute and belong to the OPC namespace if (reader.IsEmptyElement && PackagingUtilities.GetNonXmlnsAttributeCount(reader) == 1 && (String.CompareOrdinal(reader.NamespaceURI, XTable.Get(XTable.ID.OpcSignatureNamespace)) == 0)) { // ? if (String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.RelationshipReferenceTagName)) == 0) { // RelationshipReference tags are legal and these must be empty with a single SourceId attribute // get the SourceId attribute string id = reader.GetAttribute(XTable.Get(XTable.ID.SourceIdAttrName)); if (id != null && id.Length > 0) { if (relationshipSelectors == null) relationshipSelectors = new List (); // we found a legal SourceId so create a selector and continue searching relationshipSelectors.Add(new PackageRelationshipSelector(owningPartUri, PackageRelationshipSelectorType.Id, id)); continue; } } // ? else if ((String.CompareOrdinal(reader.LocalName, XTable.Get(XTable.ID.RelationshipsGroupReferenceTagName)) == 0)) { // RelationshipsGroupReference tags must be empty with a single SourceType attribute string type = reader.GetAttribute(XTable.Get(XTable.ID.SourceTypeAttrName)); if (type != null && type.Length > 0) { // lazy init if (relationshipSelectors == null) relationshipSelectors = new List (); // got a legal SourceType attribute relationshipSelectors.Add(new PackageRelationshipSelector(owningPartUri, PackageRelationshipSelectorType.Type, type)); continue; } } } // if we get to here, we have not found a legal tag so we throw throw new XmlException(SR.Get(SRID.UnexpectedXmlTag, reader.LocalName)); } } /// /// Generate Manifest tag /// /// manager /// current Xml doc /// hash algorithm to hash with /// parts to sign - possibly null /// relationshipSelectors that represent the /// relationships that have to be signed - possibly null ///internal static XmlNode GenerateManifest( PackageDigitalSignatureManager manager, XmlDocument xDoc, HashAlgorithm hashAlgorithm, IEnumerable parts, IEnumerable relationshipSelectors) { Debug.Assert(manager != null); Debug.Assert(xDoc != null); Debug.Assert(hashAlgorithm != null); // check args if (!hashAlgorithm.CanReuseTransform) throw new ArgumentException(SR.Get(SRID.HashAlgorithmMustBeReusable)); // XmlNode manifest = xDoc.CreateNode(XmlNodeType.Element, XTable.Get(XTable.ID.ManifestTagName), SignedXml.XmlDsigNamespaceUrl); // add part references if (parts != null) { // loop and write - may still be empty foreach (Uri partUri in parts) { // generate a reference tag manifest.AppendChild(GeneratePartSigningReference(manager, xDoc, hashAlgorithm, partUri)); } } // any relationship references? int relationshipCount = 0; if (relationshipSelectors != null) { relationshipCount = GenerateRelationshipSigningReferences(manager, xDoc, hashAlgorithm, relationshipSelectors, manifest); } // did we sign anything? Manifest can NOT be empty if (parts == null && relationshipCount == 0) throw new ArgumentException(SR.Get(SRID.NothingToSign)); return manifest; } //------------------------------------------------------ // // Private Methods // //----------------------------------------------------- /// /// GenerateRelationshipSigningReferences /// /// /// /// /// /// ///number of references to be signed private static int GenerateRelationshipSigningReferences( PackageDigitalSignatureManager manager, XmlDocument xDoc, HashAlgorithm hashAlgorithm, IEnumerablerelationshipSelectors, XmlNode manifest) { // PartUri - and its list of PackageRelationshipSelectors Dictionary > partAndSelectorDictionary = new Dictionary >(); foreach (PackageRelationshipSelector relationshipSelector in relationshipSelectors) { //update the partAndSelectorDictionary for each relationshipSelector Uri relationshipPartUri = PackUriHelper.GetRelationshipPartUri(relationshipSelector.SourceUri); List selectors; if (partAndSelectorDictionary.ContainsKey(relationshipPartUri)) selectors = partAndSelectorDictionary[relationshipPartUri]; else { selectors = new List (); partAndSelectorDictionary.Add(relationshipPartUri, selectors); } selectors.Add(relationshipSelector); } // now that we have them grouped by Part name, emit the XML // Here is an optimization for saving space by declaring the OPC namespace and prefix // in the tag. It will become: // // Later when we generate the RelationshipSigningReference we can use the namespace prefix "opc" // instead of the long namespace itself, thus saving some space if the manifest has more than one // RelationshipSigningReference. // XmlElement xmlE = (XmlElement)manifest; xmlE.SetAttribute(XTable.Get(XTable.ID.OpcSignatureNamespaceAttribute), XTable.Get(XTable.ID.OpcSignatureNamespace)); int count = 0; foreach (Uri partName in partAndSelectorDictionary.Keys) { // emit xml and append manifest.AppendChild( GenerateRelationshipSigningReference(manager, xDoc, hashAlgorithm, partName, /* we are guaranteed that this is a valid part Uri, so we do not use PackUriHelper.CreatePartUri */ partAndSelectorDictionary[partName])); count++; } return count; } private static Uri ParsePartUriAttribute(String attrValue, out ContentType contentType) { // extract the query portion - do not ask the Uri class for it because it will escape // characters and we want to do a simple text comparison later contentType = ContentType.Empty; // out argument must always be set int index = attrValue.IndexOf('?'); Uri uri = null; if (index > 0) { try { // ensure it starts with the correct query prefix String query = attrValue.Substring(index); if ((query.Length > _contentTypeQueryStringPrefix.Length) && (query.StartsWith(_contentTypeQueryStringPrefix, StringComparison.Ordinal))) { // truncate the prefix and validate contentType = new ContentType(query.Substring(_contentTypeQueryStringPrefix.Length)); } // now construct the uri without the query uri = PackUriHelper.ValidatePartUri(new Uri(attrValue.Substring(0, index), UriKind.Relative)); } catch (ArgumentException ae) { // Content type or part uri is malformed so we have a bad signature. // Rethrow as XmlException so outer validation loop can catch it and return validation result. throw new XmlException(SR.Get(SRID.PartReferenceUriMalformed), ae); } } // throw if we failed if (contentType.ToString().Length <= 0) throw new XmlException(SR.Get(SRID.PartReferenceUriMalformed)); return uri; } /// /// Generates a Reference tag that contains a Relationship transform /// /// manager /// name of the relationship part /// current xml document /// hash algorithm = digest method /// relationshipSelectors that represent the relationships to sign ///ContentType is known and part name can be derived from the relationship collection private static XmlNode GenerateRelationshipSigningReference( PackageDigitalSignatureManager manager, XmlDocument xDoc, HashAlgorithm hashAlgorithm, Uri relationshipPartName, IEnumerablerelationshipSelectors) { string relPartContentType = PackagingUtilities.RelationshipPartContentType.ToString(); // XmlElement reference = xDoc.CreateElement(XTable.Get(XTable.ID.ReferenceTagName), SignedXml.XmlDsigNamespaceUrl); // add Uri // persist the Uri of the associated Relationship part String relationshipPartString; if (PackUriHelper.ComparePartUri(relationshipPartName, PackageRelationship.ContainerRelationshipPartName) == 0) relationshipPartString = PackageRelationship.ContainerRelationshipPartName.ToString(); else relationshipPartString = PackUriHelper.GetStringForPartUri(relationshipPartName); XmlAttribute uriAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.UriAttrName)); uriAttr.Value = relationshipPartString + _contentTypeQueryStringPrefix + relPartContentType; reference.Attributes.Append(uriAttr); // add transforms tag (always necessary) // XmlElement transforms = xDoc.CreateElement(XTable.Get(XTable.ID.TransformsTagName), SignedXml.XmlDsigNamespaceUrl); // add Relationship transform String opcNamespace = XTable.Get(XTable.ID.OpcSignatureNamespace); String opcNamespacePrefix = XTable.Get(XTable.ID.OpcSignatureNamespacePrefix); XmlElement transform = xDoc.CreateElement(XTable.Get(XTable.ID.TransformTagName), SignedXml.XmlDsigNamespaceUrl); XmlAttribute algorithmAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); algorithmAttr.Value = XTable.Get(XTable.ID.RelationshipsTransformName); transform.Attributes.Append(algorithmAttr); // or // foreach (PackageRelationshipSelector relationshipSelector in relationshipSelectors) { switch (relationshipSelector.SelectorType) { case PackageRelationshipSelectorType.Id: { XmlNode relationshipNode = xDoc.CreateElement(opcNamespacePrefix, XTable.Get(XTable.ID.RelationshipReferenceTagName), opcNamespace); XmlAttribute idAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.SourceIdAttrName)); idAttr.Value = relationshipSelector.SelectionCriteria; relationshipNode.Attributes.Append(idAttr); transform.AppendChild(relationshipNode); } break; case PackageRelationshipSelectorType.Type: { XmlNode relationshipNode = xDoc.CreateElement(opcNamespacePrefix, XTable.Get(XTable.ID.RelationshipsGroupReferenceTagName), opcNamespace); XmlAttribute typeAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.SourceTypeAttrName)); typeAttr.Value = relationshipSelector.SelectionCriteria; relationshipNode.Attributes.Append(typeAttr); transform.AppendChild(relationshipNode); } break; default: Invariant.Assert(false, "This option should never be executed"); break; } } transforms.AppendChild(transform); // add non-Relationship transform (if any) String transformName = null; if (manager.TransformMapping.ContainsKey(relPartContentType)) { transformName = manager.TransformMapping[relPartContentType]; // let them override //Currently we only support two transforms and so we validate whether its //one of those if (transformName == null || transformName.Length == 0 || !XmlDigitalSignatureProcessor.IsValidXmlCanonicalizationTransform(transformName)) throw new InvalidOperationException(SR.Get(SRID.UnsupportedTransformAlgorithm)); // transform = xDoc.CreateElement(XTable.Get(XTable.ID.TransformTagName), SignedXml.XmlDsigNamespaceUrl); algorithmAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); algorithmAttr.Value = transformName; transform.Attributes.Append(algorithmAttr); transforms.AppendChild(transform); } reference.AppendChild(transforms); // reference.AppendChild(GenerateDigestMethod(manager, xDoc)); // - digest the virtual node list made from these Relationship tags using (Stream s = XmlDigitalSignatureProcessor.GenerateRelationshipNodeStream(GetRelationships(manager, relationshipSelectors))) // serialized node list { reference.AppendChild(GenerateDigestValueNode(xDoc, hashAlgorithm, s, transformName)); } return reference; } private static XmlNode GeneratePartSigningReference( PackageDigitalSignatureManager manager, XmlDocument xDoc, HashAlgorithm hashAlgorithm, Uri partName) { PackagePart part = manager.Package.GetPart(partName); // XmlElement reference = xDoc.CreateElement(XTable.Get(XTable.ID.ReferenceTagName), SignedXml.XmlDsigNamespaceUrl); // add Uri with content type as Query XmlAttribute uriAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.UriAttrName)); uriAttr.Value = PackUriHelper.GetStringForPartUri(partName) + _contentTypeQueryStringPrefix + part.ContentType; reference.Attributes.Append(uriAttr); // add transforms tag if necessary String transformName = String.Empty; if (manager.TransformMapping.ContainsKey(part.ContentType)) { transformName = manager.TransformMapping[part.ContentType]; // XmlElement transforms = xDoc.CreateElement(XTable.Get(XTable.ID.TransformsTagName), SignedXml.XmlDsigNamespaceUrl); // XmlElement transform = xDoc.CreateElement(XTable.Get(XTable.ID.TransformTagName), SignedXml.XmlDsigNamespaceUrl); XmlAttribute algorithmAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); algorithmAttr.Value = transformName; transform.Attributes.Append(algorithmAttr); transforms.AppendChild(transform); reference.AppendChild(transforms); } // reference.AppendChild(GenerateDigestMethod(manager, xDoc)); // using (Stream s = part.GetStream(FileMode.Open, FileAccess.Read)) { reference.AppendChild(GenerateDigestValueNode(xDoc, hashAlgorithm, s, transformName)); } return reference; } private static XmlNode GenerateDigestMethod( PackageDigitalSignatureManager manager, XmlDocument xDoc) { // XmlElement digestMethod = xDoc.CreateElement(XTable.Get(XTable.ID.DigestMethodTagName), SignedXml.XmlDsigNamespaceUrl); XmlAttribute digestAlgorithmAttr = xDoc.CreateAttribute(XTable.Get(XTable.ID.AlgorithmAttrName)); digestAlgorithmAttr.Value = manager.HashAlgorithm; digestMethod.Attributes.Append(digestAlgorithmAttr); return digestMethod; } private static XmlNode GenerateDigestValueNode(XmlDocument xDoc, HashAlgorithm hashAlgorithm, Stream s, String transformName) { // XmlElement digestValue = xDoc.CreateElement(XTable.Get(XTable.ID.DigestValueTagName), SignedXml.XmlDsigNamespaceUrl); XmlText digestValueText = xDoc.CreateTextNode(XmlDigitalSignatureProcessor.GenerateDigestValue(s, transformName, hashAlgorithm)); digestValue.AppendChild(digestValueText); return digestValue; } //Returns the sorted PackageRelationship collection from a given collection of PackageRelationshipSelectors //Note: All the selectors in the given selector collection are assumed to be for the same Part/PackageRoot //This method should be called for a part/packageroot private static IEnumerable GetRelationships( PackageDigitalSignatureManager manager, IEnumerable relationshipSelectorsWithSameSource) { SortedDictionary relationshipsDictionarySortedById = new SortedDictionary (StringComparer.Ordinal); foreach (PackageRelationshipSelector relationshipSelector in relationshipSelectorsWithSameSource) { // loop and accumulate and group them by owning Part foreach (PackageRelationship r in relationshipSelector.Select(manager.Package)) { // add relationship if(!relationshipsDictionarySortedById.ContainsKey(r.Id)) relationshipsDictionarySortedById.Add(r.Id, r); } } return relationshipsDictionarySortedById.Values; } //------------------------------------------------------ // // Private Members // //------------------------------------------------------ const string _contentTypeQueryStringPrefix = "?ContentType="; } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- QueryMatcher.cs
- HttpFileCollection.cs
- LicFileLicenseProvider.cs
- PeerObject.cs
- XMLDiffLoader.cs
- HtmlFormWrapper.cs
- XmlChoiceIdentifierAttribute.cs
- RsaKeyIdentifierClause.cs
- XmlSignificantWhitespace.cs
- SafeRegistryHandle.cs
- Sql8ExpressionRewriter.cs
- HtmlElement.cs
- InvalidCastException.cs
- DesignerView.Commands.cs
- SqlXmlStorage.cs
- ConfigViewGenerator.cs
- LoadedOrUnloadedOperation.cs
- SrgsText.cs
- GiveFeedbackEvent.cs
- TemplatePropertyEntry.cs
- GridEntry.cs
- PublisherIdentityPermission.cs
- RuntimeCompatibilityAttribute.cs
- SharedStatics.cs
- CryptographicAttribute.cs
- BitStack.cs
- IndicFontClient.cs
- RemotingConfiguration.cs
- ConditionalExpression.cs
- DrawingAttributesDefaultValueFactory.cs
- Attachment.cs
- ArraySet.cs
- CodeGroup.cs
- Subtree.cs
- BasicExpressionVisitor.cs
- RuleSetBrowserDialog.cs
- BamlTreeMap.cs
- Processor.cs
- PerspectiveCamera.cs
- TypeSystem.cs
- BuildProvidersCompiler.cs
- CompositeScriptReference.cs
- isolationinterop.cs
- JsonFormatWriterGenerator.cs
- TransactedReceiveData.cs
- CheckBoxField.cs
- Formatter.cs
- RuntimeEnvironment.cs
- TypeElement.cs
- Keywords.cs
- DoubleLink.cs
- ToolboxItemSnapLineBehavior.cs
- DataListItem.cs
- _AutoWebProxyScriptHelper.cs
- SimpleFieldTemplateUserControl.cs
- StackSpiller.Temps.cs
- DelegatedStream.cs
- HttpModuleActionCollection.cs
- WmfPlaceableFileHeader.cs
- NativeMethodsCLR.cs
- XmlSchemaValidationException.cs
- AnnouncementEndpoint.cs
- DelegatedStream.cs
- CompilerInfo.cs
- DbParameterCollectionHelper.cs
- BitmapEffectState.cs
- RootProfilePropertySettingsCollection.cs
- FileLevelControlBuilderAttribute.cs
- FontCollection.cs
- TextEffectCollection.cs
- PerformanceCountersElement.cs
- IndexedEnumerable.cs
- GatewayIPAddressInformationCollection.cs
- HttpWriter.cs
- WindowsBrush.cs
- JournalEntryStack.cs
- TrustLevelCollection.cs
- DateTimeConstantAttribute.cs
- Registration.cs
- Rotation3D.cs
- ToolStripDesignerUtils.cs
- UrlPath.cs
- SqlDuplicator.cs
- PagesChangedEventArgs.cs
- ServiceThrottle.cs
- OptimalBreakSession.cs
- RuleSettings.cs
- Util.cs
- DBBindings.cs
- XmlBinaryWriter.cs
- WebPartConnectionsCancelEventArgs.cs
- MouseEventArgs.cs
- SafeEventLogWriteHandle.cs
- ImportContext.cs
- RepeaterDesigner.cs
- TableProviderWrapper.cs
- securitycriticaldataClass.cs
- CheckPair.cs
- VisualStyleTypesAndProperties.cs
- SoapAttributes.cs