如何在 TypeScript 中保护和签署 PDF 文档
本指南展示了如何使用 Aspose.PDF FOSS 为 TypeScript 加密、认证、签署和验证 PDF 文档。Document.Save() 和 Document.Open() 负责对收件人证书进行公钥加密,而 Document.Certify()、Document.Sign() 和 Document.VerifySignatures() 负责 PAdES 风格的数字签名。它需要 Node.js 22 或更高版本。
分步指南
步骤 1:安装包
git clone https://github.com/aspose-pdf-foss/Aspose.PDF-FOSS-for-TypeScript.git
cd Aspose.PDF-FOSS-for-TypeScript
npm install
npm run build通过在新的 TypeScript 文件中导入 Document 类来验证安装——一旦包安装完成,此行应能无错误解析:
import { Document } from '@asposefoss/pdf';步骤 2:导入所需类
导入 Document 以打开、保存、签名和验证文件;以下签名和加密步骤直接传递普通选项对象,因此不需要额外的导入:
import { Document } from '@asposefoss/pdf';步骤 3:使用接收者证书加密文档
Document.Save() 接受一个 encrypt 选项,其中包含一个或多个 recipients,每个由证书(PEM 字符串或 DER 字节)、一个 algorithm 和共享的 permissions 标识:
const doc = Document.OpenFile('report.pdf');
const bytes = doc.Save({
encrypt: {
recipients: [{ certificate: recipientCertPem }],
algorithm: 'aes256', // 'aes256' (default) | 'aes128' | 'rc4'
permissions: { copying: false }, // shared across all recipients
},
});步骤 4:打开加密文档
向 Document.Open() 传递一个 recipient 选项,使用匹配的私钥和证书,或一个 PKCS#12 捆绑包:
const opened = Document.Open(bytes, {
recipient: { privateKey, certificate: recipientCertPem },
// or: recipient: { pkcs12: p12Bytes, passphrase: '…' },
});
console.log(opened.Permissions); // recovered permission flags (not enforced)
步骤 5:对文档进行认证并签名
Document.Certify() 和 Document.Sign() 均为异步操作,接受一个身份(certificate + privateKey)以及描述签名字段、外观和原因的选项。认证应首先在整个文件上进行;随后会逐步追加进一步的批准签名:
async function certifyAndSign(sourcePath: string, signaturePageIndex: number): Promise<void> {
const certifying = Document.OpenFile(sourcePath);
await certifying.Certify(
{ certificate: authorCert, privateKey: authorKey },
{
permissions: 'form-fill',
reason: 'Certifying the document',
fieldName: 'Certification',
appearance: { page: signaturePageIndex, rect: [400, 100, 550, 140] },
},
);
const certifiedBytes = certifying.Save();
const approving = Document.Open(certifiedBytes);
await approving.Sign(
{ certificate: approverCert, privateKey: approverKey },
{ reason: 'Approved for publication', fieldName: 'Approval', subFilter: 'PAdES' },
);
approving.WriteTo('signed.pdf');
}步骤 6:验证签名
Document.VerifySignatures() 是异步的,并且对每个签名字段返回一个 SignatureReport,每个都报告加密的 integrity、signature 的有效性,以及它是否 coversWholeFile:
async function verify(path: string): Promise<void> {
const doc = Document.OpenFile(path);
const reports = await doc.VerifySignatures();
for (const r of reports) {
console.log(`${r.name}: integrity=${r.integrity} signature=${r.signature} `
+ `coversWholeFile=${r.coversWholeFile} docMDP=${r.docMDP}`);
}
}常见问题与解决方案
Document.Sign() / Document.Certify() 抛出或挂起。 两者都是异步的 — await 调用。忘记 await 导致返回的 promise 未被解决,并且写入在签名完成之前就发生。
后续的批准签名会使认证失效。 增量签名:首先保存已认证的字节(certifying.Save()),使用以下方式重新打开 Document.Open(),然后调用 Sign() 在重新打开的文档上——进行完整重写而非增量追加会破坏认证的 /ByteRange 摘要。
VerifySignatures() reports coversWholeFile: false 针对第一个签名,但 true 针对最后一个。 这在先认证后签名的链中是预期的:认证在批准追加之前已经签署,因此只有最新的签名的 /ByteRange 会延伸到文件的末尾。
使用正确的私钥仍然解密失败。 确认 certificate 传递给 recipient 与文档加密时使用的确切证书相匹配于 Document.Save()的 recipients 列表 — 使用新密钥对重新颁发的证书将无法解密使用旧密钥对加密的数据。
常见问题
文档可以加密给多个收件人吗?
是的 — recipients 在 Document.Save() 的 encrypt 选项中接受数组;任何收件人的匹配私钥都可以打开生成的文件。
Document.Sign() 生成什么签名格式?
在签名选项中传入 subFilter: 'PAdES' 会生成兼容 PAdES 的签名;省略它则使用库的默认签名子过滤器。
我如何检查文档是已认证的还是仅仅签名的?
检查由 Document.VerifySignatures() 返回的 SignatureReport 上的 docMDP 字段 — 认证签名会报告 DocMDP 权限裁决;仅批准的签名则不会。
库是否强制执行在 Document.Open() 之后恢复的 Permissions?
不 — opened.Permissions 报告加密文件中记录的权限标志以供检查;在应用程序中强制执行这些标志是调用方的责任。