We 're trying to sign a PDF document using the CAdES method and the examples in dss-cookbook as a starting point using the latest version (4.6.RC1).
Following the example from SignPdfPadesBDetached.java
, we have succesfully signed a PDF document using PAdES
. However, since there is no example for CAdES
, we tried adapting the above example to use CAdES
, but
it doesn't work. Specifically the generated PDF document has a size of only 7k instead of the expected 2.5MB and the following error is displayed when trying to open the PDF:
We assume the 7k is actually only the signature so that the actual document is not included. The settings we use are:
And the relative's method code is currently this:
public static void signPdfWithCades(DSSDocument toSignDocument) {
LOG.info("Signing PDF with CADES B");
try {
AbstractSignatureTokenConnection signingToken = new Pkcs12SignatureToken("password", KEYSTORE_PATH);
DSSPrivateKeyEntry privateKey = signingToken.getKeys().get(0);
// Preparing parameters for the CAdES signature
CAdESSignatureParameters parameters = new CAdESSignatureParameters();
// We choose the level of the signature (-B, -T, -LT, -LTA).
parameters.setSignatureLevel(SignatureLevel.CAdES_BASELINE_B);
// We choose the type of the signature packaging (ENVELOPING, DETACHED).
parameters.setSignaturePackaging(SignaturePackaging.DETACHED);
// We set the digest algorithm to use with the signature algorithm. You must use the
// same parameter when you invoke the method sign on the token. The default value is
// SHA256
parameters.setDigestAlgorithm(DigestAlgorithm.SHA256);
// We set the signing certificate
parameters.setSigningCertificate(privateKey.getCertificate());
// We set the certificate chain
parameters.setCertificateChain(privateKey.getCertificateChain());
// Create common certificate verifier
CommonCertificateVerifier commonCertificateVerifier = new CommonCertificateVerifier();
// Create PAdES xadesService for signature
CAdESService service = new CAdESService(commonCertificateVerifier);
// Get the SignedInfo segment that need to be signed.
ToBeSigned dataToSign = service.getDataToSign(toSignDocument, parameters);
// This function obtains the signature value for signed information using the
// private key and specified algorithm
DigestAlgorithm digestAlgorithm = parameters.getDigestAlgorithm();
SignatureValue signatureValue = signingToken.sign(dataToSign, digestAlgorithm, privateKey);
// We invoke the cadesService to sign the document with the signature value obtained in
// the previous step.
DSSDocument signedDocument = service.signDocument(toSignDocument, parameters, signatureValue);
LOG.info("Signed PDF size = " + signedDocument.getBytes().length);
//We use the DSSUtils to Save to file
DSSUtils.saveToFile(signedDocument.openStream(), "target/signedPdfCadesBDetached.pdf");
} catch (Exception e) {
LOG.error(e.getMessage(), e);
}
}
The corresponding method for signing with PAdES
is similar to the above, adjusted to PAdES
(that is, we there used PAdESSignatureParameters
, SignatureLevel.PAdES_BASELINE_B
and PAdESService
) classes.
Please note that the SD-DSS project is not hosted in the Maven Central repository, so we had to make an explicit reference to it:
<repositories>
<repository>
<id>europa</id>
<url>https://joinup.ec.europa.eu/nexus/content/groups/public/</url>
</repository>
</repositories>
In addition, I believe we included all of the required/corresponding dependencies in our pom.xml
:
<dependency>
<groupId>eu.europa.ec.joinup.sd-dss</groupId>
<artifactId>dss-token</artifactId>
<version>4.6.RC1</version>
</dependency>
<dependency>
<groupId>eu.europa.ec.joinup.sd-dss</groupId>
<artifactId>dss-pades</artifactId>
<version>4.6.RC1</version>
</dependency>
<dependency>
<groupId>eu.europa.ec.joinup.sd-dss</groupId>
<artifactId>dss-cades</artifactId>
<version>4.6.RC1</version>
</dependency>
<dependency>
<groupId>eu.europa.ec.joinup.sd-dss</groupId>
<artifactId>dss-document</artifactId>
<version>4.6.RC1</version>
</dependency>
Prior to this, we also gave a try to PDFBox, but the documentation wasn't so helpful, according to what we want to accomplish.
Any idea what is wrong here? Changing the packaging ENVELOPING makes no difference either. Is the method for signing with CAdES so different that the PAdES example should not be used as a guide?
In general,
PAdES signatures are specifically profiled signatures embedded into a PDF. Thus, your PAdES signed PDF can be opened in Adobe Reader, and Adobe Reader can recognize the signature, verify it, and display the result of that in its signature panel.
CAdES signatures are specifically profiled signatures which either are in a separate file or which contain the signed data. Neither of these formats is recognized by Adobe Reader, in case of the separate file you can open the original PDF but the Reader does not see the signature, in case of the contained PDF the Reader either cannot open the file at all or (as the Reader ignores some leading and trailing extra bytes) considers the signature ignorable trash.
You only need a PDF aware library (like PDFBox) for PAdES signatures, for CAdES signatures the PDF is treated like generic data bytes.
In your case, therefore, i.e. for
your 7K indeed is the mere signature in a separate file and you have to keep or forward both the PDF and the signature, the PDF for viewing and the signature for verification.
Thus,
Specifically the generated PDF document has a size of only 7k instead of the expected 2.5MB ...
We assume the 7k is actually only the signature so that the actual document is not included.
Your assumption is correct, and also the behavior is correct. Yout expectations are the issue.
Some confusion might result from the facts that the signature container embedded into a PDF in case of a PAdES signature, when extracted, proves to be in CAdES format, that the matching PDF subfilter is called ETSI.CAdES.detached, and that (at least in the most recent draft at hand) the PDF 2.0 specification will treat the PAdES signatures in a section titled "12.8.3.4 CAdES signatures as used in PDF (PDF 2.0)".
Nonetheless, if you are talking about PAdES signatures, you are talking about ETSI AdES signatures integrated in PDFs. If you are talking about CAdES signatures, you are talking about ETSI AdES CMS signatures independant of a specific document format which may be detached from the signed data or which may wrap them.
According to your comments, in particular this one
Signing the PDF using
ETSI.CAdES.DETACHED
filter is the exact requirement
you in the end do not want to create a CAdES signature but instead a PAdES signature, more exactly you want to do so according to the Part 3: PAdES Enhanced - PAdES-BES and PAdES-EPES Profiles and not according to Part 2: PAdES Basic - Profile based on ISO 32000-1 which uses the subfilters adbe.pkcs7.detached and adbe.pkcs7.sha1.
(To get the requirement straight, that is the subfilter value, not the filter value.)
This is exactly what the dss cookbook examples SignPdfPadesB
, SignPdfPadesBDetached
, and SignPdfPadesBVisible
should be all about:
and that standard specifies:
6 Requirements for B-Level Conformance
This clause defines requirements that PAdES signatures claiming conformance to the B-Level have to fulfil.
The current clause specifies compliance requirements for short-term electronic signatures. This clause actually profiles PAdES-BES (signatures that do not incorporate
signature-policy-identifier
) and PAdES-EPES (signatures that do incorporatesignature-policy-identifier
) signatures.
Unfortunately I cannot now verify that the samples do what they claim as my eclipse dss projects are all red with problems.
If they do, though, it looks like you in the beginning already had what you wanted:
Following the example from SignPdfPadesBDetached.java, we have succesfully signed a PDF document using PAdES.
You may share a sample PDF signed with that example for analysis to be sure.