Digital Signatures (for
docx, pptx, xlsx)
SIGNATURES IN MICROSOFT
OFFICE
Certificate Validation
(should a signature be trusted?)
This chapter explains how to use the docx4j dig sig tool:
Dig Sig makes it easy to use docx4j to work with digital signatures:
· programmatically sign docx, pptx, or xlsx files
o with 1 or more signatures
o with or without the signature being “visible” (docx only)
· validate signatures
The implementation follows the Microsoft spec, so the signatures work as expected in Microsoft Office.
A signature can be visible (in Excel or Word) or invisible.
In either case, the signature also hashes the document (more on this below), so Office can detect whether its been “tampered” with (ie edited) after signing. This is its primary purpose: to detect whether signed data has been altered
In Word, a “visible” signature looks like this:
This is inserted using the Signature Line dialog (Insert > Singature Line):
A user can click on the Signature Line to sign it.
First they’ll see a dialog:
When someone signs it, their signature appears there:
Signatures can also be “invisible”. In this case, the document is hashed, but there is no signature on the document surface. You add an invisible digital signature via File>Info>Protect Document:
The sign dialog is similar:
In Word 2013/2016, this dialog has some additional fields:
Either way, after a document has been signed, the Signature panel gives you visual confirmation that the signatures are vald/intact (that is, that the signed parts have not been altered):
You can click to get the details:
(The information given differs a little depending on whether the signature is visible or not)
You are alerted if the signature is no longer valid:
In the case of a visual signature, you will also see red text superimposed on it:
Signatures are supported in Office 2007, 2010 and 2013, however, Powerpoint does not support visible signatures.
Signatures are not supported in Office for Mac (either 2011 or 2016).
Signing is part of the Open Packaging Conventions spec.
Docx4j Enterprise can sign documents following that spec; it can also validate signatures.
As noted in the spec:
Digital signatures do not protect data from being changed. However, consumers can detect whether signed data has been altered and notify the end-user, restrict the display of altered content, or take other actions.
It isn’t necessary to understand the full details in order to use Docx4j’s digital signature functionality. However, it is useful to understand the role of XmlSignaturePart:
· when you sign a document, you create an XmlSignaturePart
· there is an XmlSignaturePart for each signature
· the XmlSignaturePart is used for validation
An XmlSignaturePart looks something like:
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#" xmlns:dssi="http://schemas.microsoft.com/office/2006/digsig" xmlns:mdssi="http://schemas.openxmlformats.org/package/2006/digital-signature" xmlns:xd="http://uri.etsi.org/01903/v1.3.2#" Id="idPackageSignature">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></CanonicalizationMethod>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"></SignatureMethod>
<Reference Type="http://www.w3.org/2000/09/xmldsig#Object" URI="#idPackageObject">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
<DigestValue>z7n7di9KSx4VqtOfph4aLW2f2v8=</DigestValue>
</Reference>
<Reference Type="http://www.w3.org/2000/09/xmldsig#Object" URI="#idOfficeObject">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
<DigestValue>Kj6v0MJbJZSjEvWCJTqJ9Ka1wis=</DigestValue>
</Reference>
<Reference Type="http://uri.etsi.org/01903#SignedProperties" URI="#idSignedProperties">
<Transforms>
<Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"></Transform>
</Transforms>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
<DigestValue>ErjZGNguSuMk9yR5GarA7POLx4Y=</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue Id="idPackageSignature-signature-value">ejBOZSQY7fK4GcsNH2tfm2TlcwG+..qjO03wwp48BONaBD9GtG3P8jy2GbEsVM23ZaRaBRA==</SignatureValue>
<KeyInfo>
<!-- KeyInfoSignatureFacet -->
<X509Data>
<X509Certificate>MIIFGDCCBACgAwIBAgIQf9Hy8UJoFT4iDZtsk+..+JhxM8k4JSmlXwk98Oq87tkZ</X509Certificate>
</X509Data>
</KeyInfo>
<Object Id="idPackageObject">
<Manifest>
<Reference URI="/word/document.xml?ContentType=application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
<DigestValue>w8hL8o7msdLrxRjyoP0+OXvfOx8=</DigestValue>
</Reference>
:
</Manifest>
<SignatureProperties Id="id-signature-time-Wed Mar 02 11:11:48 EST 2016">
<SignatureProperty Id="idSignatureTime" Target="#idPackageSignature">
<mdssi:SignatureTime>
<mdssi:Format>YYYY-MM-DDThh:mm:ssTZD</mdssi:Format>
<mdssi:Value>2016-03-02T00:11:48Z</mdssi:Value>
</mdssi:SignatureTime>
</SignatureProperty>
</SignatureProperties>
</Object>
<Object Id="idOfficeObject">
<SignatureProperties>
<SignatureProperty Id="idOfficeV1Details" Target="#idPackageSignature">
<dssi:SignatureInfoV1>
:
<dssi:SignatureProviderDetails>0</dssi:SignatureProviderDetails>
<dssi:SignatureType>1</dssi:SignatureType>
<dssi:ManifestHashAlgorithm>http://www.w3.org/2000/09/xmldsig#sha1</dssi:ManifestHashAlgorithm>
</dssi:SignatureInfoV1>
</SignatureProperty>
</SignatureProperties>
</Object>
<Object>
<xd:QualifyingProperties Target="#idPackageSignature">
<xd:SignedProperties Id="idSignedProperties">
<xd:SignedSignatureProperties>
<xd:SigningTime>2016-02-02T11:11:48Z</xd:SigningTime>
<xd:SigningCertificate>
<xd:Cert>
<xd:CertDigest>
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></DigestMethod>
<DigestValue>zk1lWOk+1aUEe7B+bZzgO84hQy8=</DigestValue>
</xd:CertDigest>
<xd:IssuerSerial>
<X509IssuerName>[issuer]</X509IssuerName>
<X509SerialNumber>16990207296591082732488088650</X509SerialNumber>
</xd:IssuerSerial>
</xd:Cert>
</xd:SigningCertificate>
<xd:SignaturePolicyIdentifier>
<xd:SignaturePolicyImplied/>
</xd:SignaturePolicyIdentifier>
<xd:SignatureProductionPlace>
<xd:City></xd:City>
<xd:StateOrProvince></xd:StateOrProvince>
<xd:PostalCode></xd:PostalCode>
<xd:CountryName></xd:CountryName>
</xd:SignatureProductionPlace>
<xd:SignerRole>
<xd:ClaimedRoles>
<xd:ClaimedRole> </xd:ClaimedRole>
</xd:ClaimedRoles>
</xd:SignerRole>
</xd:SignedSignatureProperties>
<xd:SignedDataObjectProperties>
<xd:CommitmentTypeIndication>
<xd:CommitmentTypeId>
<xd:Identifier>http://uri.etsi.org/01903/v1.2.2#ProofOfOrigin</xd:Identifier>
<xd:Description>Created and approved
this document</xd:Description>
</xd:CommitmentTypeId>
<xd:AllSignedDataObjects/>
</xd:CommitmentTypeIndication>
</xd:SignedDataObjectProperties>
</xd:SignedProperties>
<xd:UnsignedProperties>
<xd:UnsignedSignatureProperties>
<!-- Office
2013 XAdES-X-L, not implemented in Docx4j 3.3.0 -->
<xd:CertificateValues>
<xd:EncapsulatedX509Certificate>MIIE5 .. y6vFUg=</xd:EncapsulatedX509Certificate>
<xd:EncapsulatedX509Certificate>MIIEZj ..s0AH8g=</xd:EncapsulatedX509Certificate>
</xd:CertificateValues>
</xd:UnsignedSignatureProperties>
</xd:UnsignedProperties>
</xd:QualifyingProperties>
</Object>
</Signature>
The Open Packaging Conventions spec describes how the package digital signature framework applies the W3C Recommendation “XML-Signature Syntax and Processing” with certain modifications.
The W3C Recommendation https://www.w3.org/TR/xmldsig-core/ explains how to generate a signature, and validate it. It is not necessary to understand the information in this section in any detail, in order to use Docx4j to sign or validate.
The following is quoted from the spec:
The REQUIRED steps include the
generation of Reference elements
and the SignatureValue over SignedInfo.
3.1.1 Reference Generation
For each data object being
signed:
1. Apply the Transforms, as
determined by the application, to the data object.
2. Calculate the digest value
over the resulting data object.
3. Create a Reference element,
including the (optional) identification of the data object, any (optional)
transform elements, the digest algorithm and the DigestValue. (Note, it
is the canonical form of these references that are signed in 3.1.2 and
validated in 3.2.1 .)
3.1.2 Signature Generation
1. Create SignedInfo element
with SignatureMethod, CanonicalizationMethod and Reference(s).
2. Canonicalize and then
calculate the SignatureValue over SignedInfo based
on algorithms specified in SignedInfo.
3. Construct the Signature element
that includes SignedInfo, Object(s) (if
desired, encoding may be different than that used for signing), KeyInfo (if
required), and SignatureValue.
The REQUIRED steps of core
validation include (1) reference
validation, the verification of the
digest contained in each Reference in SignedInfo, and (2)
the cryptographicsignature
validation of the signature
calculated over SignedInfo.
3.2.1 Reference Validation
1. Canonicalize the SignedInfo element
based on the CanonicalizationMethod in SignedInfo.
2. For each Reference in SignedInfo:
1. Obtain the data object to be
digested. (For example, the signature application may dereference the URI and
execute Transforms provided
by the signer in theReference element,
or it may obtain the content through other means such as a local cache.)
2. Digest the resulting data
object using the DigestMethod specified
in its Reference specification.
3. Compare the generated digest
value against DigestValue in
the SignedInfo Reference; if there
is any mismatch, validation fails.
3.2.2 Signature Validation
1. Obtain the keying information
from KeyInfo or
from an external source.
2. Obtain the canonical form of
the SignatureMethod using
the CanonicalizationMethod and
use the result (and previously obtained KeyInfo) to confirm
the SignatureValue over
the SignedInfo element.
Note that the Open Packaging Conventions modify/elaborate on these steps slightly.
In addition, the Signature panel in Office also checks certificate validity (ie in addition to reference and signature validation).
XAdES v1.4.1[1] extends XMLDSIG into the domain of non-repudiation by defining XML formats for advanced electronic signatures that remain valid over long periods and are compliant with EU-DIR-ESIG. XAdES incorporates additional useful information, including evidence as to validity even if the signer or verifying party later attempts to deny (repudiates) the validity of the signature.
XAdES includes the following seven forms:
XAdES-BES
|
provides basic authentication and
integrity protection: and satisfies the legal requirements for advanced electronic
signatures, but does not provide non-repudiation of its existence. |
Supported |
XAdES-EPES |
as above,
but it has a SignaturePolicyIdentifier element. In Office,
the SignaturePolicyIdentifier element only has the default element (SignaturePolicyImplied). |
Default |
XAdES-T |
with Time-Stamp: Includes time-stamp to provide
protection against repudiation |
Supported |
XAdES-C |
with complete validation data: Includes references to the set
of data supporting the validation of the electronic signature (i.e. the
references to the certification path and its associated revocation status
information). This form is useful for those situations where such information
is archived by an external source, like a trusted service provider. |
Not currently supported |
XAdES-X |
with eXtended validation data: Includes time-stamp on the
references to the validation data or on the ds:Signature element and the
aforementioned validation data. This time-stamp counters the risk that any
keys used in the certificate chain or in the revocation status information
may be compromised. |
Not currently supported |
XAdES-X-L |
with eXtended validation data
incorporated for the long term: Includes the validation data for those situations
where the validation data are not stored elsewhere for the long term. CertificateValues:A verifier will have to prove
that the certification path was valid, at the time of the validation of the
signature, up to a trust point according to the naming constraints and the
certificate policy constraints from the "Signature Validation
Policy". It will be necessary to capture all the certificates from the
certification path, starting with those from the signer and ending up with
those of the certificate from one trusted root of the "Signature
validation policy". RevocationValues: When dealing with long term
electronic signatures, all the revocation data used in the verification of
such signatures must be stored and conveniently time-stamped |
Could support (see CertificateTrustChecker further below) (Office 2013 & 2016 write CertificateValues) |
XAdES-A |
with archiving validation data: It includes additional
time-stamps for archiving signatures in a way that they are protected if the
cryptographic data become weak. |
(Not supported by Office) |
XAdES- EPES is the default format for Office 2010 signatures.
Docx4j follows this. The property com.plutext.dsig.XAdES.Level supports the following values:
0 - XAdES Off (Create XML-DSig signatures)
1 - Create XAdES-EPES signatures (default)
2 - Create XAdES-T signatures
Regarding XAdES-T, quoting https://blogs.msdn.microsoft.com/david_leblanc/2010/05/30/office-2010-digital-signatures-and-xades/
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.
To create an XAdES-T signature, you need to do 2 things:
1. Set docx4j property com.plutext.dsig.XAdES.Level=2 in docx4j.properties
2. Set your time stamp server:
signatureHelper.getSignatureConfig().setTspUrl(tspUrl);
and any other properties (username, proxy etc).
In this scenario you sign the package with one or more signatures (each creating an XmlSignaturePart), but the signatures are not visible on the document surface.
Basic usage (signature is not visible):
SignatureHelper signing= new SignatureHelper(pkg);
signing.configureSignature(fis, password);
signing.sign();
// then save your pkg
signing.configureSignature is used to provide the key to
be used for signing the package. Several
method signatures are available:
/**
* Provide details of a
PKCS12 key, in preparation for signing this package.
*/
public SignatureDetail configureSignature(InputStream
PKCS12stream, char[] password) throws
Docx4JException {
KeyStore keystore =
KeyStore.getInstance("PKCS12"); // a
new keystore
keystore.load(PKCS12stream, password); // now
containing one entry
:
/**
* Provide details of a
key to be used for signing this package
*
* @param
pkEntry
*/
public SignatureDetail configureSignature(KeyStore.PrivateKeyEntry pkEntry)
To use this latter method, load a keystore of your choice, then invoke its getEntry method. For more details, see https://docs.oracle.com/javase/7/docs/api/java/security/KeyStore.html
A visible signature is a “signature line” on the document surface, coupled with an XmlSignaturePart.
The two are tied together via a reference from the XmlSignaturePart to the signature line’s ID.
Before signing, the signature line will look something like:
The underlying XML:
<w:r>
<w:pict>
<v:shapetype id="_x0000_t75" coordsize="21600,21600" ..>
:
</v:shapetype>
<v:shape id="_x0000_i1025" type="#_x0000_t75" alt="Microsoft Office Signature Line..." style="width:192pt;height:96pt">
<v:imagedata r:id="rId5" o:title=""/>
<o:lock v:ext="edit" ungrouping="t" rotation="t" cropping="t" verticies="t" text="t" grouping="t"/>
<o:signatureline v:ext="edit" id="{12846971-C688-4F86-B09E-338A31F4D41B}"
o:suggestedsigner="John Doe"
o:suggestedsigner2="Manager" issignatureline="t"/>
</v:shape>
</w:pict>
</w:r>
Note:
·
the o:signatureline element
·
the rel id
in the v:imagedata element, which is to an EMF image
You can sign the document (ie add the XmlSignaturePart) at the same time as inserting the signature line, or you can do it later (via docx4j or using Word).
If the signature line is already present in the docx, you can use docx4j to sign the document (ie add the XmlSignaturePart).
After signing, the signature line will look something like:
and the signature panel should say:
Visible signatures are currently only supported for Docx files. (Excel 2010 has signature line support, but Docx4j does not currently have a high level API for creating an Excel signature line)
SignatureHelper helper= new
SignatureHelper(pkg);
CTSignatureLine sigLine = helper.createCTSignatureLine("John
Doe", true);
P p = helper.createDocxSignatureLineP(sigLine, imageRelId, null, true);
pkg.getMainDocumentPart().addObject(p);
When you insert a signature line, Word stores an EMF image of the signature block. Note that Docx4j does not currently support generating a custom signature block EMF image for a user to use to later sign. However, this does not matter if signing is done later via the Office user interface, since Office generates that image itself on-the-fly. For this reason, the sample code just uses a tiny 2 pixel image.
CTSignatureLine represents o:signatureline:
<o:signatureline v:ext="edit" id="{12846971-C688-4F86-B09E-338A31F4D41B}"
o:suggestedsigner="John Doe"
o:suggestedsigner2="Manager" issignatureline="t"/>
helper.createCTSignatureLine sets o:suggestedsigner
You can set other attributes as you see fit (eg
the signer’s title goes in o:suggestedsigner2).
To sign the document, you need a reference to the signature line object. You’ll have this if you just inserted the signature line. Otherwise, you’ll have to search the document contents to find the signature line (not explained here).
So continuing the example above:
SignatureDetail details = helper.configureSignature(fis, password);
details.setVisualSignature(sigLine,
validSigLnImg png,
signatureImage png);
helper.sign();
validSigLnImg png is critical, its the signature block image (signature plus signature line) which appears on the document surface.
If the signature is invalidated (eg the document is altered), that image will be replaced with InvalidSigLnImg. As a convenience, Docx4j can generate that image from validSigLnImg, provided you provide it inpng format. Alternatively, you can provide SignatureDetail with your own image to be used if the document is invalid:
/**
* A base64 encoded
image (Word uses EMF, but PNG tested ok with Word 2010),
* displayed in the
document if the signature is invalid; made up of the signature line plus
* the signature, plus
red text saying it is invalid.
*
* If null, can be
generated from validSigLnImg, provided that is a png
*
* @param
validSigLnImg
*/
public void setInvalidSigLnImg(String invalidSigLnImg)
In the Word UI, a user can sign visually with an image, or with text. In the above example, the visual signature is configured with a signature image: signatureImage png is an image of the signature; it doesn’t appear on the document surface, but is stored in the XmlSignaturePart.
If you wanted to sign instead with text, you’d use:
public void
setVisualSignature(CTSignatureLine signatureLine, byte[] validSigLnImg,
String signatureText)
Validate existing signatures:
SignatureHelper signing= new
SignatureHelper(pkg);
List<XmlSignaturePart> parts = signing.getSignaturesStatus(null);
for
(XmlSignaturePart sp : parts) {
System.out.println(sp.getPartName().getName() + "
---> " + sp.getSignatureStatus(null));
}
Mostly, you interact with com.plutext.dsig.SignatureHelper
Some
configuration settings are in SignatureConfig. You can access that from
SignatureHelper:
public SignatureConfig getSignatureConfig()
/**
* Provide details of a
PKCS12 key, in preparation for signing this package
*
* @param
privateKeyIS
* @param
password
* @throws
Docx4JException
*/
public SignatureDetail
configureSignature(InputStream
PKCS12stream, String password) throws
Docx4JException
/**
* Provide details of a
PKCS12 key, in preparation for signing this package.
*
* @param
privateKeyIS
* @param
password
* @param
signatureLine
* @throws
Docx4JException
*/
public SignatureDetail
configureSignature(InputStream
PKCS12stream, char[] password) throws
Docx4JException
/**
* Provide details of a
key to be used for signing this package
*
* @param
pkEntry
*/
public SignatureDetail
configureSignature(KeyStore.PrivateKeyEntry pkEntry)
/**
* Set the extra info
required to visibly sign this package
* with a textual
signature
* (associating it with
a signature line on the document surface)
*
* @param
signatureDetail
* @param
signatureLine
* @param
validSigLnImg the image (Word uses EMF,
but PNG tested ok with Word 2010
* and MUST be used
since we can't manipulate an EMF, yet),
* displayed in the
document; should be the signature line plus the signature.
* @param
signatureText
*/
public void
setVisualSignature(SignatureDetail signatureDetail,
CTSignatureLine signatureLine,
byte[] validSigLnImg, String signatureText);
/**
* Set the extra info
required to visibly sign this package
* with a graphical
signature
* (associating it with
a signature line on the document surface)
*
* @param
signatureDetail
* @param
signatureLine
* @param
validSigLnImg the image (Word uses EMF,
but PNG tested ok with Word 2010
* and MUST be used
since we can't manipulate an EMF, yet),
* displayed in the
document; should be the signature line plus the signature.
* @param
signatureImage the signature itself (not
actually displayed), but stored
*/
public void
setVisualSignature(SignatureDetail signatureDetail,
CTSignatureLine signatureLine,
byte[] validSigLnImg, byte[] signatureImage)
/**
* Sign it, using the
key provided via configureSignature
*/
public void sign() throws
Docx4JException
/**
* Signed if
SignatureOriginPart has rels to one or more XmlSignatureParts
* @return
*/
public boolean
isPackageSigned()
/**
* Set the signature status for each
signature. This mimics what you see in the Word signatures pane,
* and checks the validity of the signature
(hash), whether it is complete or partial,
* and the certificate used to sign with.
*
* @param
zippedOfficeFile a docx/pptx/xlsx file (not docx4j
package), to ensure the input has not been modified in docx4j
* @param
certificateTrustChecker
* @return
* @throws
SignaturesNotPresentException
* @throws
DigitalSignatureException
*/
public static
List<XmlSignaturePart> getSignaturesStatus(InputStream zippedOfficeFile,
CertificateTrustChecker certificateTrustChecker)
throws
SignaturesNotPresentException, DigitalSignatureException {
public
List<XmlSignaturePart> getSignaturesStatus(CertificateTrustChecker certificateTrustChecker) throws
SignaturesNotPresentException, DigitalSignatureException
You can then iterate through
the XmlSignaturePart objects, invoking getSignatureStatus(), which returns a
SignatureStatus:
public enum
SignatureStatus {
UNKNOWN,
VALID,
INVALID,
VALID_PARTIAL /* the signed parts are valid, but not all
required parts are signed */,
RECOVERABLE /* the signature is valid, but the certificate
is not trusted */,
RECOVERABLE_PARTIAL
}
/**
* Set the signature status for each
signature, without checking the validity of the
* certificate itself. This is a subset of
what you see in the Word signatures pane,
* since it checks the validity of the
signature (hash), and whether it is complete or partial,
* BUT NOT the certificate used to sign
with.
*
* @param
zippedOfficeFile a docx/pptx/xlsx file (not docx4j
package), to ensure the input has not been modified in docx4j
* @param
certificateTrustChecker
* @return
* @throws
SignaturesNotPresentException
* @throws
DigitalSignatureException
*/
public static
List<XmlSignaturePart> getSignaturesStatusTrusted(InputStream zippedOfficeFile) throws
SignaturesNotPresentException, DigitalSignatureException
/**
* Remove all signature
parts from this package
* @param pkg
*/
public void
removeSignatureParts(OpcPackage pkg)
1. Visible signatures are currently only supported for Docx files. (Excel 2010 has signature line support, but Docx4j does not currently have a high level API for creating an Excel signature line; please contact Plutext if you need this)
2. Docx4j does not currently support generating a custom signature block EMF image for a user to use to later sign. However, this does not matter if signing is done later via the Office user interface, since Office generates that image itself on-th-fly. It may matter if signing is done via some third party user interface.
Where Docx4j is used to sign the document with a visible signature, the image provided for the signed signature block will appear on the document surface.
It is possible to examine the signer to
determine whether it is to be trusted (based on trusted certificate
authorities). This is called
"certificate validation", and Word’s signature implementation does
this.
Docx4j’s SignatureHelper contains:
/**
* Set the signature status for each
signature. This mimics what you see in the Word signatures
* pane, and checks the validity of the
signature (hash), whether it is complete or partial,
* and the certificate used to sign with.
*
* @param
certificateTrustChecker pass null to use the default implementation
* @return
* @throws
SignaturesNotPresentException
* @throws
DigitalSignatureException
*/
public List<XmlSignaturePart>
getSignaturesStatus(CertificateTrustChecker certificateTrustChecker) throws
SignaturesNotPresentException, DigitalSignatureException {
You can then invoke getSignatureStatus(signatureConfig)
on an XmlSignaturePart to get its status.
The details of how check the validity of a
certificate in Java depends on your environment (including not just whether you
use Oracle or IBM java, but if Oracle java, which version, and what
certificates you want to trust).
Because of this variation, the API accepts an
object implementing:
public interface CertificateTrustChecker
{
CertificateTrustCheckResult isTrusted(X509Certificate signer) throws
DigitalSignatureException, CertPathValidatorException,
CertPathBuilderException;
}
An implementation of this is provided in DefaultCertificateTrustChecker,
however it requires Java 8.
If you pass a null CertificateTrustChecker, the certificate will not be checked, and
providing the signature is valid, the resulting SignatureStatus will be
RECOVERABLE or RECOVERABLE_PARTIAL.
The X.509 certificate for validating the
signature is located in the Digital Signature XML Signature part itself.
In contrast, the Open Packaging Conventions
also supports:
·
placing it
in a Digital Signature Certificate part
·
storing
the certificate as a separate part in the package, or
·
not
including it in the package if certificate data is known or can be obtained
from a local or remote certificate store.
The Open Packaging Convention spec / Microsoft Office supports both DSA and RSA algorithms
In Docx4j, currently only RSA is supported for
signing the digest (see SignatureInfo class).
If you have the signed docx open in the preview pane in Windows Explorer, Word may be unable to open that docx. So either turn off the preview pane, or preview some other file.
This seems to affect 64 bit versions of Word on Windows 7, 8 and 10.
Word Online can’t open signed documents (even if signed in eg Word 2013):
(the error message is misleading)
Word 2011 for Mac is silent as to whether
signatures are present.
Word 2016 for Mac detects that a docx is
signed, but doesn’t give any information about the signature.
Word 1.0.1 (16.0.4027.1006) can’t open digitally signed files.
This is fixed in Word 1.0.1 (16.06828.1002), which can open them (but can’t validate them).
If signature validation is failing, it is
helpful to understand where.
To see, turn on slf4j debug-level logging for: org.apache.jcp.xml.dsig
The following VM arguments can also provide
insight:
-Dcom.sun.net.ssl.checkRevocation=false
-Dcom.sun.security.enableCRLDP=false
-Djava.security.debug=certpath
-Djavax.net.debug=all