当前位置: 首页 > 知识库问答 >
问题:

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

楚奇逸
2023-03-14

我正在用iText7和GlobalSign DSS对PDF进行数字签名。我在必要的iText类中实现了GlobalSing DSS API调用。我得到适当的服务器响应,并且能够使用所有需要的参数调用pdfsigner.signdetached()方法。用pdfSigner签名也成功了,我得到了一个签名的PDF,乍一看很好。但是,当我在Adobe Reader中打开签名的pdf时,它告诉我签名证书的信任链被破坏了,它无法追溯到CA根目录。这很奇怪,因为它是AATL证书,而Adobe Reader的AATL列表是最新的。
我不明白为什么会发生这种情况。

我是这样做的:

>

  • 调用DSS获取标识:返回id字符串、签名证书和ocsp响应

    调用trustchain的DSS:返回用于
    对签名证书签名的证书链,直到GlobalSign根,以及
    它们的oscp响应(根除外)

    我实现了一个调用DSS API/timestamp/{digest}的ITsaClient

    最后执行:pdfsigner.signdetached(externalDigest,externalSignature,chain.toArray(new x509certifice[]{}),null,dssOcspClient,dssTSAClient,0,pdfsigner.cryptostandard.cms);

    其中externalSignature(IExternalSignature的实现)将调用DSS标识/{id}/sign/{digest}API

    这里缺少什么?

    de DSS API的trustchain响应不仅返回签名证书的信任链中的证书,还返回签名证书和GlobalSign根之间的两个中间件的ocsp响应。这些从来没有用过。事实上,我也不知道如何处理它们。
    这些可能是AdobeReader重建直到GlobalSign根的信任链所缺少的部分吗?
    如果是:我如何将它们放入PDF中?
    如果没有:那么我做错了什么,破坏了信任链?

    这些问题的答案将节省我的时间:-)

    这里是显示问题的PDF链接:
    用DSS签名的测试PDF
    (接受答案后,我根据客户的请求删除了示例PDF)

    下面是一些代码。

    收集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());
    }
    


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


    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;
    }
    
        @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);
    }
    
  • 共有1个答案

    姚昊焱
    2023-03-14

    您的签名者证书无效。

    签名者证书及其证书链(根据颁发者/主题匹配)嵌入签名中,特别是带有主题的证书

    cn=Voertuigen,ou=department Mobiliteit en Openbare Werken,ou=vlaams Huis voor de Verkeersveiligheid,o=ministeries van de Vlaamse Gemeenschap,l=brussel,st=brussel,c=be

    因此,可以检查证书签名时使用的签名。这样做时,您会看到签名者证书的tbscertificate部分(待签名部分)具有以下摘要值

    C8751FDC7F679CB627F61028ACDD0D09613AFA782412ACFC7E189EA5DA625831
    

    但签名实际上对这个摘要值进行签名

    16090737B41E6E0466E7EB7A7EBD79F5494E438C11D0FB408BCA663A5923AD03
    

    因此,您的签名者证书没有正确签名。

    这会让我大吃一惊的。

    证书签名不是为您要签名的证书部分的DER编码形式计算的,而是为其他形式计算的。

    这并不是闻所未闻的,如果您的证书最初不是DER格式的,但证书签名过程假设它是DER格式的,则可能已经签名了非DER格式(尽管根据规范必须签名DER格式)。如果某个验证器检查了签名,该签名也不确保DER形式,但采用了TBSCertificate,该验证器甚至会指示签名是有效的。

     类似资料:
    • 我正试图将我的计算机配置为信任用于测试网站的自签名证书。然而,我在Firefox上遇到了一些问题。Chrome和IE都没问题。 我做了以下几点。 使用OpenSSL创建2048位pem rsa密钥和crt 从密钥和crt文件创建pfx文件 使用MMC将pfx导入到服务器上的个人证书存储中 将IIS配置为使用站点的证书 在客户端PC上 null 我还尝试将证书直接添加到Firefox的权限列表中。它

    • 我最近升级了Inteliij IDEA 2019.2,如果我尝试从IDE中提取Git,我会发现以下错误:无法访问'https://github.xxx.com/app-Hello-USD/DGS.git/“:SSL证书问题:证书链中的自签名证书。 有人能帮我什么选项,我必须启用。 谢谢

    • 问题内容: 当尝试使用其PHP库通过Twilio发送消息时,我正在为这个错误而苦苦挣扎: 我在Windows 7上使用了wamp。 我当然找到了所有其他有关证书错误的信息。据我所知,通常更新或添加文件即可解决该问题。但是,即使这样做,我仍然遇到相同的错误。 就像这里所做的健全性检查一样,这正是我所做的: 从此处下载了最新的证书:http : //curl.haxx.se/ca/cacert.pem

    • 问题内容: 我遇到客户端https请求的问题。 片段可以如下所示: 我得到的是错误:证书链中的自签名证书。 使用邮递员时,我可以导入客户端证书和密钥,并且可以毫无问题地使用它。有没有可用的解决方案?我还希望对邮递员如何处理证书和工作方式有所了解。 问题答案: 根据您的问题,我想您正在使用SSL通讯的自签名证书进行开发。 如果是这种情况,请在您正在运行节点的任何地方或直接使用 这指示节点允许不信任的

    • 问题内容: 我试图使用(java)密钥工具创建一个自签名证书,但是当我尝试使用它时,出现以下异常(有关完整异常,请参见底部)。 我知道我可以使用以下代码绕过此代码: (资源) 但是我对此解决方案不感兴趣,因为我认为这会造成安全漏洞。(如果我错了,请纠正我)。 谁能指出我正确的方向?我目前正在本地进行测试,因此很容易进行更改。我可以访问服务器代码,客户端代码和.keystore文件。 更新资料 我试

    • 我想通过SSL连接到我的服务器。因此,我使用以下命令在服务器上生成证书: 如果我使用如下所示的TrustManager信任客户端上的所有证书,则连接可以正常工作: 但我当然不想相信所有的证书,而只相信我的证书。我尝试了以下几个命令来导入证书: 我要怎么做才能让它正常工作?有人能解释一下对一个不是很熟悉cryto领域的人所必需的步骤吗? 编辑:正如Donal Fellows所建议的那样,我尝试了自定