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

标签 java pdf digital-signature pdfbox pades

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

遵循 SignPdfPadesBDetached.java 中的示例,我们已经使用 PAdES 成功地签署了一个 PDF 文件。但是,由于没有 CAdES 的示例,我们尝试调整上面的示例以使用 CAdES,但是 它不起作用。具体而言,生成的 PDF 文档的大小仅为 7k 而不是预期的 2.5MB,并且在尝试打开 PDF 时显示以下错误:
enter image description here
我们假设 7k 实际上只是签名,因此不包括实际文档。我们使用的设置是:

  • SignatureLevel.CAdES_BASELINE_B
  • SignaturePackaging.DETACHED
  • 摘要算法.SHA256

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

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 中包含了所有必需/相应的依赖项:

<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 但阅读器看不到签名,如果是包含的 PDF,阅读器要么根本无法打开文件,要么(作为读者忽略一些前导和尾随的额外字节)认为签名是可忽略的垃圾。

对于 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”的部分中处理 PAdES 签名.3.4 PDF (PDF 2.0) 中使用的 CAdES 签名”。

不过,如果您谈论的是 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 类评论中声称展示了如何使用 PAdES-BASELINE-B 签署 PDF 文档
  • PAdES 基线配置文件的 asciidoc/dss-documentation.adoc 说明书引用了 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 以进行分析以确保确定。

关于java - 无法使用 CAdES 方法签署 PDF,尽管使用 PAdES 签署成功,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34546694/

相关文章:

flutter - 我想在我的 flutter 应用程序上正确加载其他屏幕

java - 使用 Itext 将 Pdf 页面转换为字节数组

c# - 在 ASP.Net 中使用客户端证书进行数字签名

JAVA RMIdispatchUncaughtException - 接口(interface)转换问题

java - 什么是删除——删除对泛型有哪 4 个限制?

java - 深拷贝FlatBuffer对象的方法

windows-installer - MSI 应用转换删除签名

java - 检查字符串是否包含主题标签词

ios - 具有旋转支持的 CGPDF drawPDFPage

c# - 使用 C# 将数字签名应用于 office-vba-macros