/// <summary> /// Constructor for use when opening an existing signature /// </summary> /// <param name="manager">digital signature manager - to consult for hash, embedding and other options</param> /// <param name="signaturePart">part that houses the signature</param> internal PackageDigitalSignature( PackageDigitalSignatureManager manager, PackagePart signaturePart) { _manager = manager; _processor = new XmlDigitalSignatureProcessor(manager, signaturePart, this); }
private static XmlNode GenerateDigestValueNode(XmlDocument xDoc, HashAlgorithm hashAlgorithm, Stream s, String transformName) { // <DigestValue> 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); }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ /// <summary> /// Constructor for creating a new signature /// </summary> /// <param name="manager">digital signature manager - to consult for hash, embedding and other options</param> /// <param name="processor">digital signature manager - to consult for hash, embedding and other options</param> internal PackageDigitalSignature( PackageDigitalSignatureManager manager, XmlDigitalSignatureProcessor processor) { Debug.Assert(processor.PackageSignature == null, "Logic Error: one processor per-signature"); _manager = manager; _processor = processor; // _processor.PackageSignature = this; }
/// <summary> /// Generates a Reference tag that contains a Relationship transform /// </summary> /// <param name="manager">manager</param> /// <param name="relationshipPartName">name of the relationship part</param> /// <param name="xDoc">current xml document</param> /// <param name="hashAlgorithm">hash algorithm = digest method</param> /// <param name="relationshipSelectors">relationshipSelectors that represent the relationships to sign </param> /// <remarks>ContentType is known and part name can be derived from the relationship collection</remarks> private static XmlNode GenerateRelationshipSigningReference( PackageDigitalSignatureManager manager, XmlDocument xDoc, HashAlgorithm hashAlgorithm, Uri relationshipPartName, IEnumerable <PackageRelationshipSelector> relationshipSelectors) { string relPartContentType = PackagingUtilities.RelationshipPartContentType.ToString(); // <Reference> 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) // <Transforms> 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); // <RelationshipReference SourceId="abc" /> or // <RelationshipGroupReference SourceType="xyz" /> 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> 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); // <DigestMethod> reference.AppendChild(GenerateDigestMethod(manager, xDoc)); // <DigestValue> - 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); }
/// <summary> /// Parses Transforms tag /// </summary> /// <param name="reader">node to parse</param> /// <param name="partUri">Part Uri for the part owning the relationships</param> /// <param name="relationshipSelectors">allocates and returns a list of /// PackageRelationshipSelectors if Relationship transform</param> /// <returns>ordered list of Transform names</returns> private static List <String> ParseTransformsTag(XmlReader reader, Uri partUri, ref List <PackageRelationshipSelector> relationshipSelectors) { // # reference that signs multiple PackageRelationships // <Reference URI="/shared/_rels/image.jpg.rels?ContentType=image/jpg"> // <Transforms> // <Transform Algorithm="http://schemas.openxmlformats.org/package/2006/RelationshipTransform"> // <RelationshipReference SourceId="1" /> // <RelationshipReference SourceId="2" /> // <RelationshipReference SourceId="8" /> // </Transform> // <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315" /> // </Transforms> // <DigestMethod Algorithm="sha1" /> // <DigestValue>... </DigestValue> // </Reference> // verify lack of attributes if (PackagingUtilities.GetNonXmlnsAttributeCount(reader) != 0) { throw new XmlException(SR.Get(SRID.XmlSignatureParseError)); } List <String> 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 <String>(); } 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 <String>(); } 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); }