PDFium Delphi Component 文件

FPdfAsn1 单元

单元: FPdfAsn1
以有界的资源使用对 ASN.1 区分编码规则(DER)数据进行编码、导航、解码和验证

公共类型

TypeDescription
TAsnTag通用标签常量(BOOLEAN、INTEGER、OCTET STRING、OID、SEQUENCE、SET 以及时间和字符串形式),用于标识符构造与验证
TAsnClass标识符类别:asnClassUniversal、asnClassApplication、asnClassContextSpecific 或 asnClassPrivate
TAsnIdentifier标识符类别、构造标志和 64 位标签号,包括高标签号形式
TDerTlv解析后的 TLV,包含 Offset、HeaderLength、ContentOffset、ContentLength、NextOffset 和 Identifier,无需复制源缓冲区
TDerWriter可复用的 DER 输出缓冲区和类型化编码器
TDerReader有界读取器,提供窥视、前进、跳过、期望标签、子窗口、切片和类型化解码操作
TDerByteArraysTBytes 的动态数组,供 ConcatMany 和其他多缓冲区辅助函数使用
TDerValidationErrorKind验证错误类别:dvekMalformedTlv、dvekTrailingData、深度、节点和内容限制(dvekDepthLimit、dvekNodeLimit、dvekContentLimit)、dvekUniversalForm、按类型的规范化失败(dvekBoolean、dvekInteger、dvekBitString、dvekNull、dvekOid、dvekString、dvekTime)以及 dvekSetOrder
TDerValidationError带偏移和 Depth 信息的错误记录,包含 Kind 和人类可读的消息文本
TDerValidationErrorsTDerValidationError 的动态数组,包含在 TDerValidationResult 中返回
TDerValidationOptions通过 MaxDepth、MaxNodes、MaxContentLength、MaxErrors、RequireSingleRoot 标志、可选的 ValidateSetOrder 以及 Default 类函数设定限制
TDerValidationResult验证状态,含 IsValid、NodeCount、MaximumDepth、带偏移的 Errors,以及 ErrorCount 和 FirstError 辅助成员

写入器 API

APIDescription
Clear, IsEmpty, Count, Capacity, Bytes, Finish重置或检查缓冲数据、复制快照,或转移完成的数组并重置写入器
Reserve, Append, AppendMany, AppendByte一次性扩容,并带溢出检查地追加数组、调用方持有的缓冲区、多个数组或单个字节
Wrap, WrapIdentifier, WrapConstructed用原始标识符字节、任意标识符类别和 64 位标签号,或构造型标识符包装内容
ContextSpecific, ApplicationSpecific, PrivateSpecific在不截断标识符的前提下编码低标签号或高标签号
Sequence, SequenceOf, SetOf, SetOfSorted将已编码的值组合为 SEQUENCE 或 SET 容器;SetOfSorted 按编码字节对值排序
BooleanOf, IntegerOf, UnsignedIntegerOf, IntegerBytes, EnumeratedOf编码 BOOLEAN、有符号或无符号 INTEGER、经过验证的任意 INTEGER 内容以及 ENUMERATED 值
OctetString, OctetStringOf, BitString, Null, OID将二进制、位串、NULL 和对象标识符值编码为独立的 TLV
PrintableString, Ia5String, Utf8String编码受支持的 ASN.1 字符串形式
UTCTime, GeneralizedTime, UTCTimeOf, GeneralizedTimeOf, TimeOf编码规范的时间文本或 UTC TDateTime 值,TimeOf 会选择正确的 DER 时间类型
AlgId, AlgIdWithParams构建带 NULL 或显式参数的 AlgorithmIdentifier SEQUENCE

读取器 API

APIDescription
Initialize, AtEnd, EffectiveLimit, Remaining初始化读取器并检查其有界窗口与剩余字节数
TryReadTlvAt, PeekTlv在不改变 Position 的情况下解析低或高标签号与最短确定长度
ReadNextTlv, SkipTlv仅在完整有效的 TLV 可用时前进
TryReadExpected仅在类别、构造形式和标签号全部匹配时前进
EnterConstructed在同一源数组上创建子读取器窗口,不复制内容
ContentBytes, EncodedBytes在需要所有权时复制经过验证的内容或完整 TLV 切片
TryReadBoolean, TryReadUnsignedInteger, TryReadBitString带范围和未用位检查地解码规范的原始值
TryReadString, TryReadTime, TryReadNull解码经过验证的 UTF8String、PrintableString、IA5String、DER 时间或 NULL 内容
ReadTlv, TryReadOID, ReadOID, TryReadInteger, ReadInteger提供对原始 TLV 偏移以及对象标识符和有符号整数解码的兼容性访问

验证

function ValidateDer(const Data: TBytes): TDerValidationResult; overload;
function ValidateDer(const Data: TBytes; const Options: TDerValidationOptions): TDerValidationResult; overload;

ValidateDer 检查标识符与长度的最短形式、缓冲区边界、通用原始形式、BOOLEAN、INTEGER、ENUMERATED、BIT STRING、NULL、OBJECT IDENTIFIER、受支持的字符串以及规范的时间值

默认限制允许最大深度 64、100000 个节点、每个内容值 64 MiB 以及最多报告 32 个错误,同时要求恰好一个根 TLV

ValidateSetOrder 默认禁用,因为无模式的 DER 无法区分所有 SET 与 SET OF;对于已知的 SET OF 容器(例如 CMS 属性集合)请启用它

TDerValidationOptions.Default 提供有界的默认值,TDerValidationResult.ErrorCount 和 FirstError 则简化诊断处理

公共辅助函数

function AsnIdentifier(TagClass: TAsnClass; TagNumber: UInt64; Constructed: Boolean = False): TAsnIdentifier;
function EncodeIdentifier(const Identifier: TAsnIdentifier): TBytes;
function ConcatBytes(const A, B: TBytes): TBytes;
function Concat3(const A, B, C: TBytes): TBytes;
function Concat4(const A, B, C, D: TBytes): TBytes;
function ConcatMany(const Values: TDerByteArrays): TBytes;
function EncodeOIDContent(const Dotted: AnsiString): TBytes;
function DerValidationErrorKindName(Kind: TDerValidationErrorKind): string;

FunctionDescription
AsnIdentifier由类别、标签号和构造标志构建 TAsnIdentifier,用于驱动 TDerReader.TryReadExpected
EncodeIdentifier将 TAsnIdentifier 编码为其 DER 标识符字节,包括高标签号形式
ConcatBytes, Concat3, Concat4, ConcatMany将两个、三个、四个或一个 TBytes 动态数组连接为单次分配;被 CMS 构建器广泛使用
EncodeOIDContent将点分十进制 OID 字符串编码为不含标签和长度的内容字节,以便调用方检查或重新包装 OID
DerValidationErrorKindName返回 TDerValidationErrorKind 的显示名称,用于诊断

示例

uses FPdfAsn1;

var
  Child: TDerReader;
  Data: TBytes;
  Reader: TDerReader;
  Tlv: TDerTlv;
  Validation: TDerValidationResult;
  Writer: TDerWriter;
begin
  Writer := TDerWriter.Create;
  try
    Data := Writer.Sequence(Writer.UnsignedIntegerOf(42));
  finally
    Writer.Free;
  end;

  Validation := ValidateDer(Data);
  if not Validation.IsValid then
    raise EConvertError.Create(Validation.Errors[0].MessageText);

  Reader.Initialize(Data);
  if Reader.TryReadExpected(AsnIdentifier(asnClassUniversal, 16, True), Tlv) then
    Reader.EnterConstructed(Tlv, Child);
end;

备注