Office 2010 Digital Signatures and XAdES

Shelley Gu, the program manager for Office signatures, has already posted the PM version of what we've done to improve digital signatures in the Office 2010 Engineering blog back in December. Her post is here. While Shelley did a nice job of an overview for the average user, I'd like to dive a bit more into detail. I also noticed that there are a bunch of comments to her post that haven't been answered, and I'll do that in a following post here.

While there have been a number of improvements, the biggest change has been the addition of XAdES. XAdES is an extension to the XML-DSig that provides for a number of improvements, and allows for very long-lived signatures. The first specification for XAdES showed up at https://www.w3.org/TR/XAdES/, and dates back to 2003. The full, most recent specification is 1.4.1, and can be found at https://uri.etsi.org/01903/v1.4.1/ts_101903v010401p.pdf. It takes a bit of poking around to find the exact link to the PDF, but I confirmed that the link worked and is valid as of this writing (5/30/2010).

Getting XAdES into Office turned out to be a bit of an adventure. It started off with a request to add time stamping support, and it all had to be done in a big hurry, and we'd decided not to use XAdES, because it was supposedly hard. The first iteration was very non-standard. Once I'd gotten it done, then all of a sudden we just had to use XAdES, and we were in a big hurry for that, too. Some grumbling ensued, but I went off and did it. We first implemented up to XAdES-T (explained in a moment), which is what shipped in beta 2. Some time passed, Shelley came along, and then we decided we just had to have nearly full XAdES support, taking us up to XAdES-X-L, and that needed to be done in a hurry, too (are you sensing a theme?). Getting that part done happened after beta 2, which was just short of a miracle – not much makes the bar at that stage of the game. We've ended up with XAdES support for Word, Excel, PowerPoint and InfoPath.

Now that I've been able to examine the gory details of XAdES, I'm really glad we chose to support it. The signatures we can create are far more robust than what went before, and best of all, they're backwards compatible (at least to Office 2007 – Office 2003 is ignorant of XML signatures). There's a bunch of cool (assuming you're a signature geek) stuff to work with.

There are several levels to XAdES, and a bunch of optional elements that one could implement going forward – here's the list:

  • BES – the most basic XAdES signature
  • EPES – same as above, but it has a SignaturePolicyIdentifier element. This is the form that we create by default, though it is only technically EPES – the SignaturePolicyIdentifier only has the default element.
  • T – adds a timestamp. I'd like it if this were the default, but we don't have a default timestamp server.
  • C – adds hashes and verifying information for the certificate chain and the corresponding revocation responses, whether these are CRT or OCSP responses.
  • X – adds a timestamp that covers the original signature, and any information added in the T and C forms.
  • X-L – as above, but now we have full copies of the cert chain and the revocation responses.
  • A – archival – not yet implemented by Microsoft Office

OK, but what's the reason for all this? The BES/EPES levels add a couple of minor items, and one that's interesting and critical to have. The first is the SigningTime – this is something that's not really in the XML-DSig standard, and we invented a reasonable way to store it in our app-specific Object. The existing implementation for ODF signatures in Open Office has done exactly the same thing. With XAdES support, now we have a standard way to store the signing time.

The second major item is the SigningCertificate element. This covers a really subtle attack that the XML-DSig specification didn't think of. There are real world situations where a certificate server might re-issue a certificate that has the same public and private keys as a previously issued certificate. If you had 2 certificates with the same keys, then you could substitute one for the other, and XML-DSig wouldn't be able to tell the difference – the signature would verify just fine. This doesn't seem like a problem, but let's say I had 2 certificates, one is expired, and the other isn't. Now I sign a contract with the newer certificate, and later I want out of the contract. If I can substitute in the older certificate for the newer one, then I have an expired signature, and can repudiate the signature – it isn't valid! The SigningCertificate element takes a hash of the full X509 data used to make the signature, and makes that part of the signed data – now these attacks can be caught.

There are a number of additional optional elements included in XAdES-BES/EPES that we don't use yet – I'll discuss those later.

The next level, XAdES-T is where you really get a lot of benefit. A serious problem with XML-DSig signatures is that they're not good for the long term. You are typically given a certificate that's good for 1-2 years, you sign something, and then open it 2 years later, and it's invalid. We can't replace pen and paper this way – real signatures have to be good for many years. The solution is a SignatureTimeStamp element. This uses RFC 3161 to record a timestamp of the signature value. Assuming that we can trust the timestamp server, we now have external proof of the signing time. This means that a future expiration doesn't apply, and a revocation may not apply.

I'll digress a bit and explain some of the ins and outs of expiration and revocation, and why an expired certificate should be treated the same as if it were revoked. A core problem with using CRLs (certificate revocation lists) is that they get big. When they get big, they can clog networks, and cause timeouts. One way to manage this is to just not keep revocation information for anything that's expired – you're not supposed to trust an expired cert in any case. Whether or not this happens is up to the CA operator, and hopefully will become less common as we all move to OCSP responses, which is a better system where you get an answer for that one cert, not all the certs that have ever been revoked.

If we can prove that something was signed prior to expiration, we can now safely ignore the expiration. Revocation is a different matter, and depends on when the revocation occurs and whether it was backdated. Let's say I sign something today, and then next week find out that my certificate has been exposed to an attacker. I then figure out that the attacker got me a month ago, and I'd then go revoke the cert as of a month ago. The rub here is that if I verify the signature in the next few days, it seems valid. If I verify it in a month, then it was signed after the revocation happened, and it isn't valid. If I verify it in 2 years, and the revocation information has gone away, now it's valid again! So we've made some progress, but there's clearly more to be done. Fortunately, XAdES has solutions for these problems as well.

An immediate solution is to not timestamp something immediately – you could add the timestamp later. As long as you add the timestamp prior to expiration, and check for validity at the time you add the timestamp, then we have more assurance of the revocation status. The second part of the solution is to go to the higher levels – and note that all of these are additive if you start with XAdES-BES/EPES.

XAdES-C is a little bit of an odd level. I can't understand why anyone would ever use it in most real scenarios. What's added here are hashes and issuer information for the entire certificate chain, and hashes and identifying information for the revocation responses. This assumes that we have some external store for the certificates and responses, but doesn't say anything about where to go find them. We'll allow you to create XAdES-C signatures, but I wouldn't recommend it. If we have the extended levels, then this information becomes critical.

XAdES-X provides a key piece of critical assurance – now we add a timestamp over the signature, any XAdES-T timestamps, and the information we added for XAdES-C. This has now created a situation where we can identify that the certificate chain was valid, and revocation information was obtained at a specific point in time, and more importantly, protected the XAdES-C information from tampering. Like the predecessor, I don't recommend stopping here.

XAdES-X-L now includes the full certificate chain, and full copies of the CRLs (these could get big) or OCSP responses (much better). If you're going to go past XAdES-T, this is really the next practical stop.

If you can add all of this in stages - not a current capability of Office, but something that could be done with a utility – then if the XAdES-X-L information is added just prior to expiration, you now have a very high assurance that the signature is valid, nearly indefinitely. Ah, but cryptographic algorithms seem to degrade over time. In the time I've been working with these, we've seen MD5 go from shaky to useless, and SHA-1 will no longer meet EU or US standards as of 1/1/2011, which is right around the corner. SHA-1 isn't in the same bucket as MD5, but we expect that it will get there. It isn't out of the question that over time, the same thing will happen to SHA-256, and so on. To make matters worse, the public keys start getting creaky if they're less than 2048 bits, and we can expect these to progressively degrade as well.

The solution to the problem of "algorithm rot" is in XAdES-A – this provides for an archival timestamp, and assuming that the archival timestamp uses a better set of algorithms, we've now extended the life of the signature. If you keep doing this on a regular basis, you could have a signature remain valid long after the original core crypto used to create it became worthless, which is a really neat trick. I've got a tremendous amount of respect for the people who created XAdES – they have a really elegant solution to a lot of problems. I've only found a few ambiguous parts of the specification that were a problem for me.

In addition to all the nice features above, there's also a number of optional items that could be useful in the future:

  • SignaturePolicyIdentifier – what sort of signature is it? Full document, partial document?
  • CounterSignatures – these are obviously useful
  • DataObjectFormat – you sign what you see, and what you see should be what you sign. This can be used to help clarify just how to view the data.
  • ComittmentType – what you mean by this signature
  • SignatureProductionPlace – where you signed it
  • SignerRole – also obvious
  • Data objects timestamps – can be used to show when data were created

I'm also working with the ODF board to hopefully get XAdES signatures into the ODF 1.2 specification so that we can all create signatures that will interoperate between all of the implementers of the ODF standard. So far, my proposals seem to be well received, and really happy that it has gone well thus far.

Next post will cover some of the questions I see unanswered on Shelley's post.