虽然使用PAdES签名成功,但无法使用CAdES方法签署PDF

时间:2015-12-31 12:43:25

标签: java pdf digital-signature pdfbox pades

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

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

  • SignatureLevel.CAdES_BASELINE_B
  • SignaturePackaging.DETACHED
  • DigestAlgorithm.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_B和{ {1}})类。

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

PAdESService

此外,我相信我们在<repositories> <repository> <id>europa</id> <url>https://joinup.ec.europa.eu/nexus/content/groups/public/</url> </repository> </repositories> 中包含了所有必需/相应的依赖项:

pom.xml

在此之前,我们还尝试了PDFBox,但根据我们想要完成的内容,文档并没有那么有用。

知道这里有什么问题吗?更改包装ENVELOPING也没有区别。使用CAdES进行签名的方法是否与PAdES示例不同,不应该用作指南?

1 个答案:

答案 0 :(得分:4)

一般来说,

PAdES 签名是嵌入到PDF 中的特定配置文件签名。因此,您的PAdES签名PDF可以在Adobe Reader中打开,Adobe Reader可以识别签名,验证签名,并在其签名面板中显示该签名。

CAdES 签名是专门分析的签名,其中位于单独的文件中包含签名数据。这些格式都不被Adobe Reader识别,如果单独的文件可以打开原始PDF但读者看不到签名,如果包含PDF,则Reader无法打开文件或(如Reader忽略了一些前导和尾随的额外字节)考虑签名可忽略的垃圾。

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

在您的情况下 ,即

  • SignatureLevel.CAdES_BASELINE
  • SignaturePackaging.DETACHED

您的7K确实仅仅是单独文件中的签名,您必须保留或转发PDF和签名,PDF以供查看和签名以进行验证。

因此,

  

具体而言,生成的PDF文档的大小仅为7k而不是预期的2.5MB ......

     

我们假设7k实际上只是签名,因此不包括实际文档。

您的假设是正确的,行为也是正确的。 Yout的期望是个问题。

一些混淆 可能是由于以下事实导致在PAdES签名的情况下嵌入到PDF中的签名容器在提取时被证明是CAdES格式,匹配的PDF子过滤器称为 ETSI.CAdES.detached ,并且(至少在最近的草案中)PDF 2.0规范将在标题为&#34; <的部分中处理PAdES签名。 em> 12.8.3.4 PDF(PDF 2.0)中使用的CAdES签名&#34;。

尽管如此,如果您正在谈论PAdES签名,您谈论的是集成在PDF中的ETSI AdES签名。如果您正在谈论CAdES签名,那么您所谈论的是独立于特定文档格式的ETSI AdES CMS签名,这些签名可能与签名数据分离或者可能包含它们。

根据您的评论,特别是这个

  

使用ETSI.CAdES.DETACHED过滤器签署PDF是确切的要求

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

(要获得直接要求,即子过滤器值,而不是过滤器值。)

这正是dss cookbook示例SignPdfPadesBSignPdfPadesBDetachedSignPdfPadesBVisible的全部内容:

  • 他们都在他们的JavaDoc类评论声称显示如何使用PAdES-BASELINE-B签署PDF文档
  • PAdES基线配置文件的食谱asciidoc / dss-documentation.adoc指的是ETSI TS 103 172,
  • 并且该标准指定:

      

    6 B级一致性要求

         

    本条款定义了声称符合B级要求的PAdES签名必须满足的要求。

         

    现行条款规定了短期电子签名的合规要求。本条实际上是个人资料   PAdES-BES(不包含signature-policy-identifier的签名)和PAdES-EPES(签名   确实包含signature-policy-identifier)签名。

         

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

不幸的是,我现在无法验证样本是否符合他们的要求,因为我的日食dss项目都有问题。

但是,如果他们这样做,那么看起来你刚开始已经拥有了你想要的东西:

  

按照SignPdfPadesBDetached.java的示例,我们使用PAdES成功签署了PDF文档。

您可以与该示例共享一份PDF样本,以便进行分析。