该页面可以包含自动翻译的文本。
在 C# 和 VB.NET 中向 PDF 签名添加长期验证(PAdES-LTV)信息
PDF 签名的长期验证(LTV)信息有助于在签名创建很久之后仍然验证数字签名。如果没有 LTV,一旦签名者的证书过期或吊销数据不再可用,数字签名就会变得不可验证。这对于必须长期保持可信的法律和金融类 PDF 文档而言,通常是不可接受的。

本文分为两部分:理论和实践。首先,你将了解 PAdES-LTV 签名的基础信息。然后,你将了解如何使用 Docotic.Pdf 库 在 C# 中向 PDF 签名添加 LTV 信息。你可以在 下载 C# .NET PDF 库 页面获取该库和一个免费限时许可证密钥。
PAdES - PDF 高级电子签名
欧洲电信标准协会(ETSI)已经发布了多项电子签名标准。特别是,该协会在 ETSI EN 319 142 规范中定义了 PDF 高级电子签名(PAdES)标准。PAdES 规定了如何使 PDF 签名符合欧洲 eIDAS 法规。
LTV 签名的核心概念是在 PDF 中嵌入与验证相关的信息(VRI)。这些信息使得即使签名环境不可用,仍然可以在很长时间之后验证 PDF 签名。
ETSI EN 319 142-1 规范定义了四个 PAdES 基线签名级别:B-B、B-T、B-LT 和 B-LTA。本文将重点介绍 B-LT 和 B-LTA 级别,因为它们与启用 LTV 的 PDF 签名相关。
PAdES-B-B
ETSI.CAdES.detached 格式的短期数字 PDF 签名对应此级别。在 C# 和 VB.NET 中签署 PDF 文档 文章说明了如何创建此类签名。
PAdES-B-T
B-T 签名必须满足 B-B 级别要求,并且还要包含时间戳。
PAdES-B-LT
B-LT 签名必须符合 B-T 级别。此外,PDF 文件必须包含文档安全存储(DSS)字典,其中包括以下数据:
- 信任链中的所有证书
- 在线证书状态协议(OCSP)响应
- 证书吊销列表(CRLs)
高级电子签名对应此级别。
PAdES-B-LTA
B-LTA 签名必须符合 B-LT 级别。此外,PDF 文件必须包含文档时间戳签名和 VRI 用于文档时间戳证书的信息。
合格电子签名对应此级别。
PAdES 验证
一种方法是使用 Adobe Acrobat Pro 或 Adobe Reader。打开签名面板并展开数字签名以检查其状态。如果签名有效,你会看到“签名已启用 LTV”或“签名未启用 LTV,且将在稍后过期”。

另一种方法是使用欧盟委员会的 PAdES 验证器。该方法在验证符合欧盟(eIDAS)要求的文档时效果最佳。
ETSI 还提供了签名一致性检查器。该服务主要面向从事签名或验证工具开发的开发人员。
请注意,这些验证器对同一 PDF 文档可能给出不同的结果。

在 C# 和 VB.NET 中创建支持 LTV 的 PDF 签名
该开始写代码了!Docotic.Pdf 提供了 PdfDocument.AddLtvInfo 方法,用于向 PDF 签名添加 LTV 信息。若要生成 B-LTA 签名,你还需要使用 PdfDocument.TimestampAndSave 方法 以文档时间戳签名的方式保存 PDF。
如何在 C# 中创建 PAdES-B-LT 签名
创建 B-LT 签名的过程由三个步骤组成:
- 创建 B-T 签名并保存文档。
- 打开已签名文档并添加 LTV 信息。
- 逐步保存最终文档。
下面是用于创建 B-LT 签名的 C# 代码。你也可以从 GitHub 下载完整的 创建支持 LTV 的 PDF 签名 示例项目:
// 1. 创建 PAdES-B-T 签名
using var step1 = new MemoryStream();
using (var pdf = new PdfDocument())
{
var options = new PdfSigningOptions(..)
{
DigestAlgorithm = PdfDigestAlgorithm.Sha256,
Format = PdfSignatureFormat.CadesDetached,
};
options.Timestamp.AuthorityUrl = new Uri("http://timestamp.digicert.com");
pdf.SignAndSave(options, step1);
}
// 2. 打开已签名文档并添加 LTV 信息
using (var pdf = new PdfDocument(step1))
{
pdf.AddLtvInfo();
// 3. 逐步保存最终文档
var incrementalOptions = new PdfSaveOptions()
{
WriteIncrementally = true,
};
pdf.Save("b-lt.pdf", incrementalOptions);
}
这里有几个关键点需要注意。首先,你可以使用 PKCS#12 证书(.pfx 或 .p12 文件)或外部签名器创建 PdfSigningOptions。无论使用哪种方法,为了符合 PAdES 要求,Format 选项都必须设置为 PdfSignatureFormat.CadesDetached。
此代码片段使用了 http://timestamp.digicert.com,但你也可以使用其他时间戳机构(TSA)。以下是一些常见替代项:
http://timestamp.comodoca.com/rfc3161
http://timestamp.sectigo.com
http://timestamp.entrust.net/TSS/RFC3161sha2TS
http://rfc3161timestamp.globalsign.com/advanced
为符合 ETSI 规范,你应使用经过 eIDAS 批准的 TSA。你可以使用 EU/EEA Trusted List Browser 进行选择。
在第一步之后保存中间文档是强制性的。你必须先签名并保存文档,然后才能附加 LTV 信息。不过,这条规则有一个例外,我会在下面的 使用 LTV 认证 PDF 章节中说明。
第三步中的 WriteIncrementally = true 行启用了增量保存。增量更新不会使数字签名失效。在添加 LTV 信息时,你应始终以增量方式保存 PDF 文件。
如何在 C# 中创建 PAdES-B-LTA 签名
生成 B-LTA 签名的过程类似,只是第三步不同。你应该:
- 创建 B-T 签名并保存文档。
- 打开已签名文档并添加 LTV 信息。
- 以增量方式保存最终文档,并附带文档时间戳签名。
下面的代码示例展示了如何在 C# 中创建 B-LTA 签名:
var timestampAuthorityUrl = new Uri("http://timestamp.digicert.com");
// 1. 创建 PAdES-B-T 签名
using var step1 = new MemoryStream();
using (var pdf = new PdfDocument())
{
var options = new PdfSigningOptions(..)
{
DigestAlgorithm = PdfDigestAlgorithm.Sha256,
Format = PdfSignatureFormat.CadesDetached,
};
options.Timestamp.AuthorityUrl = timestampAuthorityUrl;
pdf.SignAndSave(options, step1);
}
// 2. 打开已签名文档并添加 LTV 信息
using (var pdf = new PdfDocument(step1))
{
pdf.AddLtvInfo();
// 3. 以增量方式保存最终文档,并附带文档时间戳签名
var timestampOptions = new PdfSignatureTimestampOptions
{
AuthorityUrl = timestampAuthorityUrl,
};
var incrementalOptions = new PdfSaveOptions()
{
WriteIncrementally = true,
};
pdf.TimestampAndSave(timestampOptions, "b-lta.pdf", incrementalOptions);
}
最终的 b-lta.pdf 文档包含两个签名——第一步中的主签名和第三步中的文档时间戳签名。你可能会注意到,Adobe Acrobat 会为这两个签名都显示“签名已启用 LTV”消息。为什么文档时间戳签名在 AddLtvInfo 调用之后创建,却仍然可以启用 LTV?
关键在于为签名时间戳和文档时间戳使用同一个
TSA
。AddLtvInfo 方法会为时间戳证书添加
VRI
。随后,文档时间戳会使用同一证书并重用关联数据。
无法为文档时间戳使用相同的 TSA?我会在 PAdES-B-T 到 B-LTA 的转换 章节中说明这种情况。
在 C# 和 VB.NET 中向现有 PDF 签名添加 LTV 信息
到目前为止,我一直是在从零开始创建支持 LTV 的签名。不过,通常也需要修改现有的 PAdES-B-T 签名。例如,将其转换为 B-LT 或 B-LTA,或者刷新 LTV 信息。
与前面的示例一样,你需要:
- 打开已签名文档并添加 LTV 信息。
- 以增量方式保存最终文档,可带或不带文档时间戳签名。
下面是相应的代码片段。
如何在 C# 中将 PAdES-B-T 签名转换为 B-LT
using var pdf = new PdfDocument("b-t.pdf");
pdf.AddLtvInfo();
var incrementalOptions = new PdfSaveOptions()
{
WriteIncrementally = true,
};
pdf.Save("b-lt.pdf", incrementalOptions);
如何在 C# 中将 PAdES-B-T 签名转换为 B-LTA
using var pdf = new PdfDocument("b-t.pdf");
pdf.AddLtvInfo();
var timestampOptions = new PdfSignatureTimestampOptions
{
AuthorityUrl = new Uri("http://timestamp.digicert.com"),
};
var incrementalOptions = new PdfSaveOptions()
{
WriteIncrementally = true,
};
pdf.TimestampAndSave(timestampOptions, "b-lta.pdf", incrementalOptions);
在 GitHub 上下载完整的 将 LTV 信息添加到现有签名 示例项目。
为文档时间戳签名添加 LTV 信息
现有的 B-T 签名可能使用与本示例不同的任意 TSA 。在这种情况下,Adobe Acrobat 会为文档时间戳签名显示“签名未启用 LTV”消息。
如何让它启用 LTV?你需要为文档时间戳签名添加 LTV 信息:
var timestampOptions = new PdfSignatureTimestampOptions
{
AuthorityUrl = new Uri("http://timestamp.digicert.com"),
};
var incrementalOptions = new PdfSaveOptions()
{
WriteIncrementally = true,
};
using var intermediate = new MemoryStream();
using (var pdf = new PdfDocument("b-t.pdf"))
{
pdf.AddLtvInfo();
pdf.TimestampAndSave(timestampOptions, intermediate, incrementalOptions);
}
// 为文档时间戳签名添加 LTV 信息
using (var pdf = new PdfDocument(intermediate))
{
pdf.AddLtvInfo();
pdf.TimestampAndSave(timestampOptions, "b-lta.pdf", incrementalOptions);
}
在 C# 和 VB.NET 中使用 LTV 认证 PDF
已认证 PDF 文档中的数字签名不允许任何修改。PDF 阅读器应用会使用特殊图标并显示以“由认证”开头的标题来表示此类签名。

对已认证 PDF 的任何更改都会使签名失效,这意味着你无法在不破坏认证的情况下添加 LTV 信息。
Docotic.Pdf 支持在生成已认证 PDF 文档时同时包含 LTV 信息。使用 AddLtvInfo(PdfSigningOptions) 重载 可在签名过程中添加 LTV 信息。下面的代码示例演示了如何在 C# 中使用 B-LT 签名认证 PDF:
using var pdf = new PdfDocument();
var options = new PdfSigningOptions(..)
{
DigestAlgorithm = PdfDigestAlgorithm.Sha256,
Format = PdfSignatureFormat.CadesDetached,
Type = PdfSignatureType.AuthorNoChanges,
};
options.Timestamp.AuthorityUrl = new Uri("http://timestamp.digicert.com");
pdf.AddLtvInfo(options);
pdf.SignAndSave(options, "certified-b-lt.pdf");
在 GitHub 上查看 使用 LTV 签名认证 PDF 代码示例。
截至 2025 年 6 月,Adobe Acrobat 支持带有 B-LT 签名的已认证 PDF 文档,但会将已认证文档中的 B-LTA 签名视为无效。
结论
你可以向 PDF 签名添加长期验证(LTV)信息,以确保法律合规性和长期可信性。PAdES 标准为 PDF 签名定义了规则和符合级别。
建议至少使用 PAdES-B-T 签名进行签名。B-T 签名可以在不破坏现有验证的情况下转换为高级电子签名(B-LT)或合格电子签名(B-LTA)。
在 .NET 应用程序中,使用 Docotic.Pdf 库 向 PDF 签名添加 LTV 信息。你甚至可以为 PDF 文档添加 LTV 认证。
在 GitHub 上查看PDF 中数字签名的代码示例。如需更多信息,请查看以下相关文章:
常见问题
如何避免 Adobe Acrobat 中显示“签名有效性未知”消息?
当 Adobe Acrobat 无法验证签名者的证书时,会显示“签名有效性未知”警告。这通常发生在证书缺失、不受信任、自签名、已吊销、已过期或尚未生效时。
获取正确的证书 以避免该警告,或创建符合欧盟(eIDAS)要求的文档。
另外,你也可以手动将证书添加到 Adobe Acrobat 的“受信任证书”中。该选项位于:菜单 > 首选项 > 签名 > 身份和受信任的证书。
如果需要为已认证文档信任某个证书,请确保授予相应权限:

如何检查 PDF 签名是否已启用 LTV?
你可以使用 Adobe Reader 或欧盟委员会的 PAdES 验证器。更多详情请参阅 PAdES 验证 章节。
为什么 Adobe Acrobat 会显示“签名未启用 LTV”?
Adobe Acrobat 会在签名验证过程中检查吊销信息。如果它需要下载任何数据,相应的签名就不会启用 LTV。
如何使 PDF 签名符合 ETSI 规范?
请遵循PDF 高级电子签名的要求。你需要使用 欧盟信任列表(EUTL) 中列出的提供商颁发的证书。
如何在 Adobe Reader 中显示“签名已启用 LTV”指示?
首先,签名必须至少符合 PAdES-B-T 级别。然后,你需要添加 LTV 信息,包括信任链中的所有证书、 OCSP 响应,以及 CRLs 。
创建启用 LTV 的 PDF 签名 和 向现有 PDF 签名添加 LTV 信息 章节说明了如何在 C# 和 VB.NET 中添加 LTV 信息。
如何为文档时间戳签名启用 LTV?
该过程与普通 PDF 签名类似。你需要将文档时间戳签名的 LTV 信息添加到 DSS 字典中。
请参阅 为文档时间戳签名添加 LTV 信息 章节中的代码示例。
是否可以在同一操作中同时执行 LTV 和时间戳?
可以!请查看 如何将 PAdES-B-T 签名转换为 B-LTA 章节中的代码示例。
如何在 C# 中创建带有 LTV 的数字签名?
使用 Docotic.Pdf 库。若要生成高级电子签名,请查看 如何创建 PAdES-B-LT 签名 章节中的代码示例。若要创建合格电子签名,请查看 如何创建 PAdES-B-LTA 签名 章节。
当“不允许更改”时,如何为签名启用 LTV?
对于已认证文档,Adobe Acrobat 要求所有 LTV 数据都包含在原始签名文档中。更多详情请阅读 使用 LTV 认证 PDF 章节。
如何在外部签名 PDF 文档时启用长期验证(LTV)?
使用 Docotic.Pdf 库 通过 USB 令牌、智能卡或基于云的 HSM 对 PDF 文档进行 LTV 签名。请查看 如何使用 USB 令牌和 HSM 设备在 C# 和 VB.NET 中为 PDF 签名 文章和 如何创建 PAdES-B-LT 签名 章节。
如何对包含多个签名的 PDF 启用 LTV?
结合 由多人签署 PDF 表单 和 将 LTV 信息添加到现有签名 代码示例。