无法使用 CAdES 方法签署 PDF,尽管使用 PAdES 签署成功

Cannot sign a PDF with CAdES method, although signing it with PAdES succeeds

我们正在尝试使用 CAdES 方法和 dss-cookbook 中的示例作为使用最新版本 (4.6.RC1) 的起点来签署 PDF 文档。

按照SignPdfPadesBDetached.java的例子,我们已经使用PAdES成功签署了一个PDF文件。但是,由于没有 CAdES 的示例,我们尝试修改上面的示例以使用 CAdES,但是 它不起作用。具体来说,生成的 PDF 文档的大小仅为 7k 而不是预期的 2.5MB,并且在尝试打开 PDF 时显示以下错误:

We assume the 7k is实际上只有签名,因此不包括实际文件。我们使用的设置是:

目前亲戚的方法代码是这样的:

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);
    }
}

对应的签名方式PAdES和上面类似,调整为PAdES(也就是我们这里用的PAdESSignatureParametersSignatureLevel.PAdES_BASELINE_BPAdESService) 类.

请注意,SD-DSS 项目未托管在 Maven 中央存储库中,因此我们必须明确引用它:

<repositories>
    <repository>
        <id>europa</id>
        <url>https://joinup.ec.europa.eu/nexus/content/groups/public/</url>
    </repository>
</repositories>

此外,我相信我们在 pom.xml:

中包含了所有 required/corresponding 依赖项
<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>

在此之前,我们也尝试过PDFBox,但根据我们想要完成的目标,文档并没有太大帮助。

知道这里出了什么问题吗?改变包装 ENVELOPING 也没有什么区别。使用 CAdES 签名的方法是否如此不同以至于不应将 PAdES 示例用作指南?

一般来说,

PAdES 签名是 嵌入到 PDF 中的特别描述的签名。因此,您的 PAdES 签名 PDF 可以在 Adob​​e Reader 中打开,并且 Adob​​e Reader 可以识别签名、验证它并在其签名面板中显示签名结果。

CAdES 签名是专门配置的签名,它们 在单独的文件中 或者 包含签名数据。 Adobe Reader 无法识别这两种格式,如果是单独的文件,您可以打开原始 PDF,但 Reader 看不到签名,如果是包含的 PDF,则 Reader 要么根本无法打开文件,要么(因为 Reader 忽略了一些前导和尾随的额外字节)认为签名是可忽略的垃圾。

对于 PAdES 签名,您只需要一个 PDF 感知库(如 PDFBox),对于 CAdES 签名,PDF 被视为通用数据字节。


在你的情况下,因此,即

  • SignatureLevel.CAdES_BASELINE
  • SignaturePackaging.DETACHED

你的7K确实是单独文件中的签名,你必须保留或转发PDF和签名,PDF用于查看,签名用于验证。

因此,

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.

你的假设是正确的,行为也是正确的。你的期望是问题所在。


一些混淆 可能是由于签名容器在 PAdES 签名的情况下嵌入到 PDF 中,提取时,证明是 CAdES 格式,匹配的 PDF 子过滤器称为 ETSI.CAdES.detached,并且(至少在手头的最新草案中)PDF 2.0 规范将处理标题为“12.8.3.4 CAdES 签名在 PDF (PDF 2.0)”部分中的 PAdES 签名。

不过,如果您谈论的是 PAdES 签名,那么您就是在谈论集成在 PDF 中的 ETSI AdES 签名。如果您谈论的是 CAdES 签名,那么您就是在谈论独立于特定文档格式的 ETSI AdES CMS 签名,该格式可能与签名数据分离或可能将它们包装起来。


根据您的意见,尤其是这一条

Signing the PDF using ETSI.CAdES.DETACHED filter is the exact requirement

你最终不是想要创建一个CAdES签名而是PAdES 签名,更确切地说,您希望根据 第 3 部分:PAdES 增强 - PAdES-BES 和 PAdES-EPES 配置文件 而不是根据 第 2 部分:PAdES 基础 - 基于 ISO 32000-1 的配置文件,它使用子过滤器 adbe.pkcs7.detachedadbe.pkcs7.sha1 .

(为了直接说明要求,即 subfilter 值,而不是 filter 值。)

这正是 dss 说明书示例 SignPdfPadesBSignPdfPadesBDetachedSignPdfPadesBVisible 的全部内容:

  • 他们都在他们的 JavaDoc class 评论中声称要展示 How to sign PDF Document with PAdES-BASELINE-B,
  • 食谱 asciidoc/dss-documentation.adoc PAdES 基线配置文件 指的是 ETSI TS 103 172,
  • 并且该标准规定:

    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 incorporate signature-policy-identifier) signatures.

    (ETSI TS 103 172 V2.1.1 (2012-03))

不幸的是,我现在无法验证样本是否按照他们声称的那样进行,因为我的 eclipse dss 项目都出现问题。

不过,如果他们这样做了,那么看起来您一开始就已经拥有了想要的东西:

Following the example from SignPdfPadesBDetached.java, we have succesfully signed a PDF document using PAdES.

您可以共享使用该示例签名的示例 PDF 以供分析以确保确定。