简体   繁体   English

iText7 pdf 使用 GlobalSign DSS AATL 证书签名显示 Adobe Reader 中的信任链损坏

[英]iText7 pdf signing with GlobalSign DSS AATL certificate shows broken trustchain in Adobe Reader

I am digitally signing a PDF with iText7 and GlobalSign DSS.我正在使用 iText7 和 GlobalSign DSS 对 PDF 进行数字签名。 I implemented the GlobalSing DSS API calls into the necessary iText classes.我在必要的 iText 类中实现了 GlobalSing DSS API 调用。 I get the proper server responses and I am able to call the pdfSigner.signDetached() method with all the needed arguments.我得到了正确的服务器响应,并且能够使用所有需要的 arguments 调用 pdfSigner.signDetached() 方法。 Signing with the pdfSigner also succeeds and I get a signed PDF that looks good at first sight.使用 pdfSigner 签名也成功了,我得到了一个签名的 PDF,乍一看还不错。 But when I open the signed pdf in Adobe Reader it tells me that the trust chain of the signing certificate is broken and that it can not trace it back to the CA root.但是,当我在 Adobe Reader 中打开签名的 pdf 时,它告诉我签名证书的信任链已损坏,并且无法将其追溯到 CA 根。 Which is strange because it is an AATL certificate and the AATL list of the Adobe Reader is up to date.这很奇怪,因为它是一个 AATL 证书,并且 Adobe Reader 的 AATL 列表是最新的。
And I do not understand why this is happening.我不明白为什么会这样。

This is what I do:这就是我所做的:

  • call DSS for an identity: returns an id string, the signing certificate and an ocsp response为身份调用 DSS:返回 id 字符串、签名证书和 ocsp 响应

  • call DSS for the trustchain: returns the chain of certificates used to为信任链调用 DSS:返回用于
    sign the signing certicate, up to the GlobalSign root, together with签署签名证书,直到 GlobalSign 根,连同
    their oscp responses (except for the root)他们的 oscp 响应(除了根)

  • I create an array of X509Certificate objects containing the signing我创建了一个包含签名的 X509Certificate 对象数组
    certificate, 2 intermediates and the GlobalSign root certificate (in that order)证书、2 个中间证书和 GlobalSign 根证书(按此顺序)

  • I implement an IOcspClient that uses the ocsp response from the DSS call for the identity我实现了一个 IOcspClient,它使用来自 DSS 调用的 ocsp 响应来获取身份

  • I implement an ITsaClient that calls the DSS API /timestamp/{digest}我实现了一个调用 DSS API /timestamp/{digest} 的 ITsaClient

  • and finally I execute: pdfSigner.signDetached(externalDigest, externalSignature, chain.toArray(new X509Certificate[]{}), null, dssOcspClient, dssTSAClient, 0, PdfSigner.CryptoStandard.CMS);最后我执行: pdfSigner.signDetached(externalDigest, externalSignature, chain.toArray(new X509Certificate[]{}), null, dssOcspClient, dssTSAClient, 0, PdfSigner.CryptoStandard.CMS);

  • in which the externalSignature (an implementation of IExternalSignature) will call the DSS identity/{id}/sign/{digest} API其中 externalSignature(IExternalSignature 的实现)将调用 DSS 身份/{id}/sign/{digest} API

While debugging into the signDetached method and deeper into the pdfSigner code, I clearly see that all certificates are in the chain in the right order.在调试 signDetached 方法并深入 pdfSigner 代码时,我清楚地看到所有证书都以正确的顺序在链中。 I see them being processed in the PdfPKCS7 class (however I don't know/understand exactly what is going on there).我看到它们正在 PdfPKCS7 class 中处理(但是我不知道/不了解那里到底发生了什么)。 I see the signing taking place, no exceptions are thrown and at the end the produced PDF looks like it is correctly signed.我看到正在签名,没有抛出异常,最后生成的 PDF 看起来像是正确签名的。 Which Adobe says is not. Adobe 说的不是。

What am I missing here?我在这里想念什么?

The trustchain response from de DSS API not only returns the certificates from the chain of trust of the signing certificate, but also the ocsp responses for the two intermediates between the signing certificate and the GlobalSign root.来自 de DSS API 的信任链响应不仅返回签名证书信任链中的证书,还返回签名证书和 GlobalSign 根之间的两个中间体的 ocsp 响应。 These are never used.这些从未使用过。 And in fact I don't know what to do with them either.事实上,我也不知道如何处理它们。
Could these be the missing pieces for AdobeReader to reconstruct the trust chain up to the GlobalSign root?这些可能是 AdobeReader 重建到 GlobalSign 根的信任链所缺少的部分吗?
And if so: how do I put them into that PDF?如果是这样:我如何将它们放入 PDF 中?
And if not: then what am I doing wrong that breaks that trustchain?如果不是:那我做错了什么破坏了信任链?

An answer to these questions would save my day:-)这些问题的答案将节省我的一天:-)

Here is the link to a PDF that will show the problem:这是 PDF 的链接,它将显示问题:
test pdf signed with DSS 测试用 DSS 签名的 pdf
(after accepting the answer, I removed the example pdf on my client's request) (接受答案后,我根据客户的要求删除了示例 pdf)

Below are some pieces of the code.下面是部分代码。

The center piece that gathers the DSS info and calls the signDetached method收集 DSS 信息并调用 signDetached 方法的中心部分

    private InputStream sign(byte[] unsignedDocument) throws IOException, DssServiceException, GeneralSecurityException {

    SigningIdentity signingIdentity = signingIdentityService.getValidSigningIdentity();
    DssOcspClient dssOcspClient = new DssOcspClient(signingIdentity);

    TrustChainResponse trustChainResponse = digitalSigningService.getTrustChain();
    List<X509Certificate> chain = new ArrayList<>();
    chain.add(signingIdentity.getCertificate());
    chain.addAll(trustChainResponse.getTrustChain());

    IExternalDigest externalDigest = new ProviderDigest(BC_SECURITY_PROVIDER);
    IExternalSignature externalSignature = new DssExternalSignature(signingIdentity.getIdentity(), digitalSigningService);

    ByteArrayOutputStream signedPdfOut = new ByteArrayOutputStream();
    PdfSigner pdfSigner = createPdfSigner(new ByteArrayInputStream(unsignedDocument), signedPdfOut);
    pdfSigner.signDetached(externalDigest, externalSignature, chain.toArray(new X509Certificate[]{}), null, dssOcspClient, dssTSAClient, 0, PdfSigner.CryptoStandard.CADES);

    return new ByteArrayInputStream(signedPdfOut.toByteArray());
}


The IExternalSignature implementation IExternalSignature 实现

    @Override
public byte[] sign(byte[] message) throws GeneralSecurityException {
    MessageDigest messageDigest = new BouncyCastleDigest().getMessageDigest(DEFAULT_DIGEST_ALGORITHM);
    byte[] documentHash = messageDigest.digest(message);
    try {
        return digitalSigningService.getSignature(signingIdentity, documentHash);
    }
    catch (DssServiceException e) {
        LOGGER.error("error getting signature", e);
        throw  new GeneralSecurityException(e);
    }
}


The IOcspClient implementation IOcspClient 实现

    @Override
public byte[] getEncoded(X509Certificate checkCert, X509Certificate issuerCert, String url) {
    try {
        if(Objects.equals(signingIdentity.getCertificate(), checkCert)) {
            OCSPResp response = new OCSPResp(signingIdentity.getOcsp());
            BasicOCSPResp basicResponse = (BasicOCSPResp)response.getResponseObject();
            return basicResponse.getEncoded();
        }
    }
    catch (CertificateException | IOException | OCSPException e) {
        LOGGER.warn("OCSP validatie gefaald!", e.getMessage());
    }
    return null;
}


The ITSAClient implementation ITSAClient 实施

    @Override
public byte[] getTimeStampToken(byte[] imprint) throws Exception {

    String digestAlgorithmOID = DigestAlgorithms.getAllowedDigest(DEFAULT_DIGEST_ALGORITHM);
    ASN1ObjectIdentifier digestAlgOID = new ASN1ObjectIdentifier(digestAlgorithmOID);
    AlgorithmIdentifier algID = new AlgorithmIdentifier(digestAlgOID, DERNull.INSTANCE);
    MessageImprint messageImprint = new MessageImprint(algID, imprint);

    byte[] hash = messageImprint.getHashedMessage();
    return digitalSigningService.getTimeStamp(hash);
}

In short简而言之

Your signer certificate is invalid.您的签名者证书无效。

In detail详细地

Your signer certificate and its certificate chain (according to issuer/subject match) are embedded in the signature, in particular your certificate with subject您的签名者证书及其证书链(根据颁发者/主题匹配)嵌入签名中,特别是您的带有主题的证书

cn=Homologatie Voertuigen, ou=Departement Mobiliteit en Openbare Werken, ou=Vlaams Huis voor de Verkeersveiligheid, o=Ministeries van de Vlaamse Gemeenschap, l=Brussel, st=Brussel, c=BE cn=Homologatie Voertuigen, ou=Departement Mobiliteit en Openbare Werken, ou=Vlaams Huis voor de Verkeersveiligheid, o=Ministeries van de Vlaamse Gemeenschap, l=Brussel, st=Brussel, c=BE

and its claimed issuer及其声称的发行人

cn=GlobalSign CA 5 for AATL, o=GlobalSign nv-sa, c=BE cn=针对 AATL 的 GlobalSign CA 5,o=GlobalSign nv-sa,c=BE

Thus, one can check the signature with which your certificate is signed.因此,可以检查您的证书所使用的签名。 And while doing so one sees that the TBSCertificate part of your signer certificate (the to-be-signed part) has this digest value在这样做的同时,您会看到签名者证书的TBSCertificate部分(待签名部分)具有此摘要值

C8751FDC7F679CB627F61028ACDD0D09613AFA782412ACFC7E189EA5DA625831

but the signature actually signs this digest value但签名实际上签署了这个摘要值

16090737B41E6E0466E7EB7A7EBD79F5494E438C11D0FB408BCA663A5923AD03

Thus, your signer certificate is not correctly signed.因此,您的签名者证书未正确签名。

What does this mean这是什么意思

In a comment you ask在你问的评论中

But I am a little confused about what it means exactly.但我对它的确切含义有点困惑。 Are we actually doing something wrong during signing, sending the wrong document hash to the signing server?我们真的在签名过程中做错了什么,将错误的文档 hash 发送到签名服务器吗? Or do you mean there is something wrong with the server side signing certificate issued by GlobalSign that they use to sign that document hash?还是您的意思是 GlobalSign 颁发的用于签署该文档 hash 的服务器端签名证书有问题?

You're not doing anything wrong during signing, at least I don't think so.你在签约的时候没有做错什么,至少我不这么认为。 The broken signature is not the signature signing the document but its the signature signing your certificate by your CA.损坏的签名不是签署文档的签名,而是您的 CA 签署您的证书的签名。

I see essentially three possible reasons for that:我基本上看到了三个可能的原因:

  • The certificate signature simply is broken and doesn't match your certificate anywhere, anyhow.证书签名只是被破坏了,无论如何都与您的证书不匹配。

    This would surprise me.这会让我感到惊讶。

  • The certificate signature has been calculated not for the DER encoded form of your to-be-signed certificate part but some other form.证书签名不是针对您要签名的证书部分的 DER 编码形式计算的,而是针对其他形式的。

    This is not unheard of , if your certificate originally was not in DER form but the certificate signing process assumed it to be, a non-DER form may have been signed (even though according to specification the DER form has to be signed).这并非闻所未闻,如果您的证书最初不是 DER 形式,但证书签名过程假定它是,则可能已经签署了非 DER 形式(即使根据规范必须签署 DER 形式)。 If some validator then checked the signature which also does not ensure DER form but takes the TBSCertificate as is, that validator would even have indicated that the signature was valid.如果某个验证器随后检查了签名,该签名也不能确保 DER 形式,而是按原样获取 TBSCertificate,那么该验证器甚至会表明该签名是有效的。

    In the certificate as embedded in the PDF signature the to-be-signed part is DER encoded but this may have been enforced at some step after the initial certificate generation.在嵌入在 PDF 签名中的证书中,待签名部分是 DER 编码的,但这可能在初始证书生成后的某个步骤被强制执行。

  • Some minute change may have happened to your certificate after creation.创建后,您的证书可能发生了一些微小的变化。

    This also is possible.这也是可能的。

You could try and receive a copy of your certificate from your CA in a form that is as original as possible and compare to the certificate that is embedded in your signature.您可以尝试以尽可能原始的形式从您的 CA 接收您的证书副本,并与嵌入在您签名中的证书进行比较。 If you find differences, then analyzing the differences most likely will further illuminate the cause of the problem.如果您发现差异,那么分析差异最有可能将进一步阐明问题的原因。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM