Teknik makale

PDFlibPas: PAdES signing and validation in Delphi

losLab PDF Library, Delphi ve C++Builder ekiplerine masaüstü, sunucu, DLL, ActiveX ve Dylib iş akışları için kaynak kodlu bir PDF motoru sağlar; dahili PDF/A ve PDF/UA kontrolleri, PAdES imzalama ve belgeleri harici PDF servisine göndermeden renderer seçimi sunar.

Bu yazı teams that need to create, inspect, and validate signed PDF workflows inside Delphi applications için hazırlanmıştır. PAdES signing and validation konusunu tek bir bileşen çağrısı olarak değil, üretim düzeyinde belge mühendisliği olarak ele alır.

Pratik risk şudur: signature creation and signature validation are often implemented separately, causing mismatched trust decisions when timestamps, revocation data, or incremental updates change. Bu nedenle akışın yazılı sözleşmeye, gözlemlenebilir tanılara ve gerçekçi regresyon dosyalarına ihtiyacı vardır.

Mimari kararlar

Use one trust policy for signing and validation. accepted certificate stores, chain policy, timestamp source, and revocation source / PAdES profile, long-term validation requirements, and archive retention period

  • accepted certificate stores, chain policy, timestamp source, and revocation source
  • PAdES profile, long-term validation requirements, and archive retention period
  • whether warnings create a block, manual review, or documented waiver
  • how later document changes are restricted after the trusted revision

Uygulama akışı

Validate the final signed revision, not the draft. Aşağıdaki sıra, iş akışını Delphi ve C++Builder ekipleri için incelenebilir tutar.

  1. prepare the document and collect validation prerequisites before signing
  2. apply the signature, timestamp, and revocation evidence according to policy
  3. validate the final signed file and classify every warning
  4. store trust evidence with the business record rather than only inside the PDF
  5. revalidate representative files when trust anchors or policy change

Doğrulama kanıtı

Trust evidence for signed documents. Bu alanları çıktı veya destek kaydıyla birlikte saklayın.

  • signature status, byte range, digest algorithm, signer certificate, and chain result
  • timestamp token status, revocation source, DSS/VRI presence, and validation time
  • policy version, warning classification, and waiver decision
  • final signed file hash and validator result

Long-term validation needs supporting data

PAdES workflows need certificate-chain checks, timestamps, revocation data, DSS/VRI information, byte-range validation, and policy decisions for warnings. The final file must be validated after all signing bytes are written.

Müşteri tarafından görülen davranış

Kullanıcılar dahili çağrı sırasını görmez. Dosyanın açılıp açılmadığını, doğrulanıp doğrulanmadığını, yazdırılıp yazdırılmadığını, düzenlenip düzenlenmediğini, içe aktarılıp aktarılmadığını veya reddedilip reddedilmediğini görürler. The workflow should translate PAdES signing and validation results into states users can act on.

  • prepare the document and collect validation prerequisites before signing
  • apply the signature, timestamp, and revocation evidence according to policy
  • validate the final signed file and classify every warning
  • a signature can be cryptographically intact but untrusted by current policy
  • revocation services may be unavailable when the document is signed

Mühendislik inceleme notları: PAdES signing and validation

Özelliğin bir demoyu aşıp sürüm, destek ve müşteri eskalasyonu sırasında savunulabilir olduğunu doğrulamak için bu inceleme notlarını kullanın.

  • Karar: accepted certificate stores, chain policy, timestamp source, and revocation source. Uygulama baskı noktası: apply the signature, timestamp, and revocation evidence according to policy. Kabul kanıtı: policy version, warning classification, and waiver decision. Regresyon tetikleyicisi: clock differences can make timestamp and certificate validity hard to explain
  • Karar: PAdES profile, long-term validation requirements, and archive retention period. Uygulama baskı noktası: validate the final signed file and classify every warning. Kabul kanıtı: final signed file hash and validator result. Regresyon tetikleyicisi: a signature can be cryptographically intact but untrusted by current policy
  • Karar: whether warnings create a block, manual review, or documented waiver. Uygulama baskı noktası: store trust evidence with the business record rather than only inside the PDF. Kabul kanıtı: signature status, byte range, digest algorithm, signer certificate, and chain result. Regresyon tetikleyicisi: revocation services may be unavailable when the document is signed

Sınır durumları

  • a signature can be cryptographically intact but untrusted by current policy
  • revocation services may be unavailable when the document is signed
  • incremental updates after signing need a clear allowed-change policy
  • clock differences can make timestamp and certificate validity hard to explain

Delphi / C++Builder notes

PDFlibPas should sit behind a small service boundary that receives files, streams, profiles, and credentials, then returns output paths, warnings, metrics, and validation status. Important terms include PAdES, signature validation, timestamp, revocation, DSS, byte range.

Delphi kod örneği

Aşağıdaki Delphi taslağı bu konu için pratik bir servis sınırını gösterir. Politika kontrollerini, günlüklemeyi ve doğrulamayı dar ürün çağrısı bölümünün dışında tutarak akışı test edilebilir bırakın.

procedure ValidatePadesPackage(const InputFile: string; const TrustPolicy: TTrustPolicy);
var
  Pdf: TPDFlib;
  ProcessId: Integer;
begin
  Pdf := TPDFlib.Create;
  try
    ProcessId := Pdf.NewSignProcessFromFile(InputFile, '');
    CheckByteRange(Pdf, ProcessId);
    ValidateCertificatePath(Pdf, ProcessId, TrustPolicy);
    Pdf.ReleaseSignProcess(ProcessId);
  finally
    Pdf.Free;
  end;
end;

Üretim kontrol listesi

  • İş akışını boş bir dosyada, normal bir müşteri dosyasında ve en kötü durum dosyasında çalıştırın
  • Oluşturulan PDF'yi hedef görüntüleyici, doğrulayıcı, yazıcı veya aşağı akış uygulamasıyla açın
  • Ürün sürümünü, profil sürümünü, giriş karmasını, çıktı yolunu, geçen süreyi ve uyarı sayısını kaydedin
  • Parolaları, sertifikaları, geçici dosyaları ve müşteri verilerini açık saklama kuralları altında tutun
  • Bir müşteri dosyası yeni bir uç durum ortaya çıkardığında regresyon belgeleri ekleyin

Ürün belgeleri

PDFlibPas

Ek kod örnekleri

var
  Pdf: TPDFlib;
  StsId: Integer;
  HashHex, TstDer, TsAttr, AugmentedCms: AnsiString;
begin
  Pdf := TPDFlib.Create;
  try
    StsId := Pdf.NewPAdESSignatureTimeStampProcessFromFile('invoice-signed.pdf', '');
    Pdf.SetPAdESSignatureTimeStampField(StsId, 'Sig1');
    Pdf.SetPAdESSignatureTimeStampDigestAlgorithm(StsId, 2);
    HashHex := Pdf.GetPAdESSignatureValueHashHex(StsId);
    // both calls below are application code: an HTTP POST to your TSA,
    // and a CMS re-encode that attaches the token as an unsigned attribute
    TstDer := RequestTimeStampToken(HashHex);
    TsAttr := Pdf.BuildPAdESSignatureTimeStampAttribute(TstDer);
    AugmentedCms := AttachUnsignedAttribute(Pdf.GetPAdESSignatureCMSBytes(StsId), TsAttr);
    Pdf.SetPAdESSignatureCMSBytes(StsId, AugmentedCms);
    Pdf.EndPAdESSignatureTimeStampProcessToFile(StsId, 'invoice-bt.pdf');
    if Pdf.GetPAdESSignatureTimeStampProcessResult(StsId) <> 1 then
      raise Exception.Create('timestamp embedding failed');
    Pdf.ReleasePAdESSignatureTimeStampProcess(StsId);
  finally
    Pdf.Free;
  end;
end;
var
  Doc: TPDFlibSignDoc;
  Names: TStringList;
  I: Integer;
  B0, B1, B2, B3, FileSize: Int64;
begin
  FileSize := TFile.GetSize('invoice-bt.pdf');  // before Open: SignDoc holds a share lock
  Doc := TPDFlibSignDoc.Create;
  try
    if not Doc.Open('invoice-bt.pdf', '', False) then
      raise Exception.Create('cannot open for audit');
    Names := TStringList.Create;
    try
      Doc.GetSignatureFieldNames(Names);
      for I := 0 to Names.Count - 1 do
        if Doc.GetSignatureValueObjNum(Names[I]) > 0 then   // >0 means actually signed
        begin
          B0 := StrToInt64(string(Doc.GetSignatureValueByName(Names[I], 11)));
          B1 := StrToInt64(string(Doc.GetSignatureValueByName(Names[I], 12)));
          B2 := StrToInt64(string(Doc.GetSignatureValueByName(Names[I], 13)));
          B3 := StrToInt64(string(Doc.GetSignatureValueByName(Names[I], 14)));
          if (B0 = 0) and (B2 + B3 = FileSize) then
            Writeln(Names[I], ': covers the file to EOF')
          else
            Writeln(Names[I], ': earlier revision, or unexpected ByteRange layout');
        end;
    finally
      Names.Free;
    end;
    Doc.Close;
  finally
    Doc.Free;
  end;
end;