xmlms-wordwordmlxml-dsig

XML Relationship Transform Algorithm


I'm trying to validate a MS Word *.docx file with digital signature. In order to do validation, i have to calculate digest of referenced nodes and to check if it is same as one given in the signature (sig1.xml). I can't find info about how ti implement relationship transformation in order to calculate that digest.

the part of signature XML (sig1.xml) is as follows:

<Object Id="idPackageObject" xmlns:mdssi="http://schemas.openxmlformats.org/package/2006/digital-signature">
<Manifest><Reference URI="/_rels/.rels?ContentType=application/vnd.openxmlformats-package.relationships+xml">
<Transforms><Transform Algorithm="http://schemas.openxmlformats.org/package/2006/RelationshipTransform">    
<mdssi:RelationshipReference SourceId="rId1"/></Transform>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/></Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>1vWU/YTF/7t6ZjnE44gAFTbZvvA=</DigestValue>....(next ref node ....)..
<Reference URI="/word/document.xml?ContentType=application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>s2yQEJrQSfC0YoRe1hvm+IGBpJQ=</DigestValue></Reference>.....More Reference Nodes.....

/_rels/.rels file himself:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml"/>
<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml"/>
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml"/>
<Relationship Id="rId4" Type="http://schemas.openxmlformats.org/package/2006/relationships/digital-signature/origin" Target="_xmlsignatures/origin.sigs"/>
</Relationships>

So i need to calculate SHA1 of /_rels/.rels, but before calculation i must apply relationship transform and C14N.

When i'm calculating digest of node with no relationship transform(of this node, for example:)

<Reference URI="/word/document.xml?ContentType=application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml"> 
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>s2yQEJrQSfC0YoRe1hvm+IGBpJQ=</DigestValue>
</Reference> 

everything is fine, just doing SHA1 of referred URI(/word/document.xml in this case) gives me same hash as one given int the signature node. But when it comes to node with relationship transform - calculations never gives same value as stated in the signature.

My Question in general is where to find info about this relationship transform and how to implement it ?

Thanks,

Georgi


Solution

  • The main source of information on transforms, and relationship transforms in this case, can be found in ECMA's "Office Open XML File Formats — Open Packaging Conventions" paper. Link here.

    The section of importance is 13.2.4.24.

    Relationship Transform should create a copy of the .rels file, in this case "/_rels/.rels" and remove all Relationship nodes that don't match with SourceId. This file is what is eventually hashed and creates the digest.

    The package implementer shall remove all Relationship elements that do not have either an Id value that matches any SourceId value or a Type value that matches any SourceType value, among the SourceId and SourceType values specified in the transform definition.

    Under step 3, "Prepare for canonicalization" it also states:

    The package implementer shall add a TargetMode attribute with its default value, if this optional attribute is missing from the Relationship element

    Because we are creating a relationship between files in the same package, we have the value of "Internal". You need to add this attribute before you hash it.

    So after the transform and c14n, you should have:

    <Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Target="word/document.xml" TargetMode="Internal" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"></Relationship></Relationships>
    

    NOTE: If you are using a unix system, be aware of linebreaks, the OPC uses CRLF not LF.