Estimated read time: 3 minutes
After adding support for SHA-256 hashes in LibreOffice, I turned towards implementing OOXML signature import (as in: verification, not signing) in LibreOffice. First, thanks to the Dutch Ministry of Defense who made this work possible (as part of a project implementing trusted signing and communication in LibreOffice), I collected a list of building blocks needed for this to work:
support for the Relationships Transform Algorithm (described in ISO/IEC 29500-2:2012) in xmlsec
an actual XML parser for the OOXML signature in
a new filter flag, so that our code no longer assumes "is ODF" means "supports digital signing" and
some refactoring in
xmlsecurity/, so that our digital signature code doesn’t assume that multiple signatures are always written to a single file
The xmlsec bits are now upstream, it seems to me that new algorithm is needed, so that MSO can avoid signing a number of streams (files in ZIP containers), while still being able to verify that all normal streams are signed. Given that MSO by default doesn’t sign all streams (so that e.g. the metadata of the document can be modified without invalidating signatures), this is in use even for a hello-world document. This implies that a typical OOXML signature will never gain the best "signed" category in LO, as we’ll always warn that even though the signature is valid, not all streams are signed. This is a bit of a rant, but better not hide the reality: a default ODF signature covers more than a default OOXML signature.
The OOXML signature parser had to extract all information from the signature markup that’s interesting for LibreOffice, like the certificate, the signature date or the signature description. I considered extending the ODF signature parser instead of implementing a new one for OOXML, since both markups are based on the same W3C signing spec, but they are different enough that the added complexity doesn’t outweigh the benefit of code sharing here.
The next step was to add a new
SUPPORTSSIGNING filter flag in
mark the DOCX, XLSX and PPTX file filters as such, and then of course find
places mostly in
xmlsecurity/ that assume only ODF files can be
signed, and modifying those checks to also handle this new flag.
Finally, a difference between ODF and OOXML signatures is that ODF puts all of them in a single stream, and all the signing and verifying code works with that stream. However, in case of OOXML, all signatures are in separate streams, so if we want to work with a single object as kind of a signature context, we need a storage (a sub-directory inside the ZIP container), and work with that.
Putting all of these together, we now have unit tests that take test documents having "good" and "bad" signatures, and the verification result in LO will match with the one of MSO. As usual, you can try this right now with a 5.2 daily build. :-)