尽管配置正确,但为什么我的数字签名 PDF 在 Adobe Acrobat 中无效?

问题描述 投票:0回答:1

我正在开发一个项目,需要使用 Node.js 对 PDF 进行数字签名。我的目标是使用 .pfx 证书签署 PDF 并包含时间戳 (TSA)。然而,尽管遵循了预期的流程,Adobe Acrobat 仍报告签名无效。证书本身有效,并且签名的文件通过了 ITI 验证程序(巴西官方数字签名验证程序)的验证,但未在 Acrobat 中通过验证。

我做了什么:

1.  Used the @signpdf/signpdf library for signing.
2.  Added a ByteRange placeholder with @signpdf/placeholder-plain.
3.  Configured the TSA using the URL: https://freetsa.org/tsr.
4.  Ensured the .pfx certificate matches the private key.
const fs = require('fs');
const { plainAddPlaceholder } = require('@signpdf/placeholder-plain');
const { SignPdf } = require('@signpdf/signpdf');
const { P12Signer } = require('@signpdf/signer-p12');

// Paths
const pdfPath = '../resources/pdf-entrada.pdf'; // Input PDF
const pfxPath = '../resources/certificado.pfx'; // PFX certificate
const signedPath = '../resources/output-signed.pdf'; // Final signed PDF
const pfxPassword = 'your_password_here'; // Certificate password
const tsaUrl = 'https://freetsa.org/tsr'; // TSA URL

async function signPdfWithTSA() {
  try {
    console.log('--- Start of Signing Process ---');
    console.log('[1] Reading the original PDF...');
    const pdfBuffer = fs.readFileSync(pdfPath);
    console.log(`[1] Original PDF size: ${pdfBuffer.length} bytes`);

    console.log('[2] Adding ByteRange (Placeholder for signature)...');
    const pdfWithPlaceholder = plainAddPlaceholder({
      pdfBuffer,
      reason: 'Digital Signature',
      contactInfo: '[email protected]',
      name: 'Your Name',
      location: 'City / Country',
    });
    console.log(`[2] PDF with Placeholder size: ${pdfWithPlaceholder.length} bytes`);

    console.log('[3] Reading the PFX certificate...');
    const pfxBuffer = fs.readFileSync(pfxPath);
    console.log(`[3] PFX certificate size: ${pfxBuffer.length} bytes`);

    console.log('[4] Configuring signer with TSA...');
    const signer = new P12Signer(pfxBuffer, { passphrase: pfxPassword, tsaUrl });
    const signPdf = new SignPdf();

    console.log('[5] Signing the PDF...');
    const signedPdfBuffer = await signPdf.sign(pdfWithPlaceholder, signer);
    console.log(`[5] Signed PDF size: ${signedPdfBuffer.length} bytes`);

    console.log('[6] Saving the signed PDF...');
    fs.writeFileSync(signedPath, signedPdfBuffer);
    console.log(`[6] Signed PDF saved at: ${signedPath}`);
    console.log('--- End of Signing Process ---');
  } catch (error) {
    console.error('Error while signing the PDF:', error.message || error);
  }
}

signPdfWithTSA();

我的控制台输出:

--- Start of Signing Process ---
[1] Reading the original PDF...
[1] Original PDF size: 22368 bytes
[2] Adding ByteRange (Placeholder for signature)...
[2] PDF with Placeholder size: 39989 bytes
[3] Reading the PFX certificate...
[3] PFX certificate size: 9200 bytes
[4] Configuring signer with TSA...
[5] Signing the PDF...
[5] Signed PDF size: 39989 bytes
[6] Saving the signed PDF...
[6] Signed PDF saved at: ../resources/output-signed.pdf
--- End of Signing Process ---

问题:

  • Adobe Acrobat 显示签名无效。
  • 它指出,尽管配置了 TSA,但该文档是使用计算机的本地时间进行签名的。
  • 签名的文件通过了 ITI 验证程序,但未通过 Acrobat。

签名 PDF 的链接

javascript node.js pdf digital-signature
1个回答
0
投票

Adobe Acrobat 显示签名无效。

简而言之, 您的签名者证书具有 Acrobat 明确不接受的证书策略 OID。您需要不同类型的证书。

详细来说,我们来看看Adobe到底是怎么说的:

Signature panel screen shot

因此,从加密角度来说,签名是可以的(“尚未修改”),问题是 Acrobat 不接受您的证书(“签名者的证书无效”)。因此,签名有效性问题与您的代码无关。

为什么 Acrobat 认为您的证书无效?我们来看看 Acrobat 证书查看器中的证书:

Certificate viewer

正如您在底部看到的,Acrobat 在您的证书中发现了无效的策略限制。这是指我在右侧“详细信息”选项卡上选择的“证书策略”值:您的证书已使用 OID 2.16.76.1.2.1.133 的证书策略创建。

但是请查看根“Autoridade Certificadora Raiz Brasileira v5”证书条目的“策略”选项卡:

Root Policies tab

这里可以看到签名者证书有Policy值限制。不幸的是,我们无法滚动允许的证书策略字段,但查看 Acrobat 的数据文件可以找到可接受的 OID 范围:

  • 2.16.76.1.2.3.1 - 2.16.76.1.2.3.138
  • 2.16.76.1.2.4.1 - 2.16.76.1.2.4.58

如您所见,当您的证书具有来自 2.16.76.1.2.1.* 分支的策略时,仅接受来自 2.16.76.1.2.3.* 和 2.16.76.1.2.4.* OID 分支的值。

换句话说,Acrobat 明确将像您这样的证书排除在信任之外。如果您希望其他用户的 Acrobat 实例接受您的签名,则必须切换到 Acrobat 信任的证书。

它指出,尽管配置了 TSA,但该文档是使用计算机的本地时间进行签名的。

分析嵌入的签名容器,确实没有嵌入时间戳令牌。因此,由于某种原因,您的代码没有嵌入它。由于我不知道所使用的签名 API,因此我无法建议进一步的措施。

签名的文件通过了 ITI 验证程序,但未通过 Acrobat。

不同的验证器可能对签名应用不同的验证例程。特别是可接受的签名者证书的范围(由信任锚和附加限制定义)可能会有所不同。

如上所述,Acrobat 仅接受由“Autoridade Certificadora Raiz Brasileira v5”颁发的签名者证书(如果它们包含某些证书策略 OID 条目)。 ITI 也可能允许其他 OID 范围,或者可能完全忽略策略 OID。

© www.soinside.com 2019 - 2024. All rights reserved.