Security

Security

本页涵盖密码、加密和数字签名。Document.OpenFile() / Document.Open() 接受密码以打开受保护的文档,Document.Save() 接受 encrypt 选项来保护文档,且 Document.Sign() / Document.Certify() / Document.VerifySignatures() 添加并检查数字签名。


打开并解密受密码保护的文档

将 { password: '...' } 传递给 Document.OpenFile() 或 Document.Open() 以打开受用户密码保护的文档。如果密码缺失或错误,调用会抛出 InvalidPasswordError。

import { Document, InvalidPasswordError } from '@asposefoss/pdf';

try {
  const doc = Document.OpenFile('secret.pdf', { password: 'hunter2' });
  doc.WriteTo('decrypted.pdf');    // output is plaintext
} catch (e) {
  if (e instanceof InvalidPasswordError) console.error('wrong password');
  else throw e;
}

保存时加密

Document.Save()(以及 Document.WriteTo())接受一个 encrypt 选项。基于密码的加密是常见情况;库还支持使用公钥对一个或多个接收者证书进行加密,随后使用接收者的私钥再次打开。

// Encrypt to one or more recipient certificates (PEM string or DER bytes):
const bytes = doc.Save({
  encrypt: {
    recipients: [{ certificate: recipientCertPem }],
    algorithm: 'aes256',                 // 'aes256' (default) | 'aes128' | 'rc4'
    permissions: { copying: false },     // shared across all recipients
  },
});

// Open with the recipient's private key + certificate, or a PKCS#12 bundle:
const opened = Document.Open(bytes, {
  recipient: { privateKey, certificate: recipientCertPem },
});
console.log(opened.Permissions);         // recovered permission flags (not enforced)

签名与认证

Document.Certify() 添加一个认证(作者)签名,携带一个 DocMDP 转换,声明后续允许的更改;Document.Sign() 添加另一个普通的批准签名,可以在其上增量追加。两者都接受一个 { certificate, privateKey } 签署者和一个选项对象(reason、location、name、fieldName,以及——针对 Certify()——permissions)。

const certifying = Document.OpenFile('report.pdf');
await certifying.Certify(
  { certificate: author.certificate, privateKey: author.privateKey },
  { permissions: 'form-fill', reason: 'Certifying the report', fieldName: 'Certification' },
);
const certifiedBytes = certifying.Save();

const approving = Document.Open(certifiedBytes);
await approving.Sign(
  { certificate: approver.certificate, privateKey: approver.privateKey },
  { reason: 'Approved for publication', fieldName: 'Approval' },
);
approving.WriteTo('signed.pdf');

验证签名

Document.VerifySignatures() 检查文档中的每个签名:它重新计算每个 /ByteRange 摘要,验证分离的 CMS,并报告每个签名之后的更改。它返回一个 SignatureReport[],每个签名对应一个条目。

const reports = await Document.OpenFile('signed.pdf').VerifySignatures();
for (const r of reports) {
  console.log(r.name, 'integrity:', r.integrity, 'signature:', r.signature);
}

技巧与最佳实践

  • 在打开不可信输入时,先专门捕获 InvalidPasswordError,再使用更广泛的捕获,这样可以对错误密码和损坏文件作出不同的响应。
  • 在任何 Sign() 调用之前先调用 Certify() —— 认证签名确定了后续批准签名所叠加的 DocMDP 权限。
  • Document.Open() 在公钥解密后返回恢复的 Permissions,但库本身并不强制执行它们 —— 将其视为信息性数据。
  • VerifySignatures() 是 async —— 在读取报告数组之前 await 它(或处理返回的 Promise)。

常见问题

问题原因修复
Document.OpenFile() / Document.Open() 抛出 InvalidPasswordError文档受密码保护,但未提供密码或提供了错误的密码将 { password: '...' } 传递给 Document.OpenFile() / Document.Open()
公钥解密失败传递了错误的私钥或证书,或两者均未匹配加密时使用的任何 recipients 条目确认 recipient 选项的 privateKey / certificate(或 PKCS#12 捆绑)与原始收件人之一匹配
批准签名会使认证失效Sign() 被调用时使用了认证 DocMDP 转换不允许的权限在 Certify() 上设置一个 permissions 值(例如 'form-fill'),足够宽松以容纳后续签署者将进行的更改
VerifySignatures() 报告完整性检查失败签名后的字节被修改,超出了签名所覆盖的增量更新范围在进行任何进一步编辑后重新签署文档

FAQ

Sign 与 Certify 有何区别?

Certify() 添加第一个认证签名,并通过 DocMDP 转换声明后续允许的更改。Sign() 添加普通批准签名,逐步追加在之前的内容之上。

如何打开受密码保护的 PDF?

将 { password: '...' } 传递给 Document.OpenFile() 或 Document.Open(),如果密码可能错误,则捕获 InvalidPasswordError。

此库是否强制执行 PDF 权限标志?

不。Document.Open() 从加密文档中恢复 Permissions 标志供您检查,但它本身并不限制您的代码对打开的文档可以执行的操作。

我该如何检查已签名的 PDF 的签名是否仍然有效?

调用 Document.VerifySignatures() (an async method) 并检查每个返回的 SignatureReport 的 integrity 和 signature 字段。


API Reference 摘要

类/方法描述
Document.OpenFile() / Document.Open()打开文档,可选密码或公钥保护
InvalidPasswordError当密码缺失或错误时抛出
Document.Save() / Document.WriteTo()保存文档,可选使用 encrypt 选项
Permissions从加密文档中恢复的权限标志
Document.Certify()添加带有 DocMDP 转换的认证(作者)签名
Document.Sign()添加批准签名
Document.VerifySignatures()验证文档中的每个签名
SignatureReport单个签名的验证结果:name、integrity、signature

另请参阅

 中文