기술 문서

HotPDF Component: Delphi에서 digital signatures and PAdES-ready signing

HotPDF는 Delphi 및 C++Builder 애플리케이션을 위한 네이티브 VCL PDF 라이브러리입니다. 외부 PDF 런타임 배포 없이 PDF 생성, 편집, 양식, 주석, 암호화, 디지털 서명, Unicode 글꼴 처리, 표준 지향 출력, 프리플라이트 보고를 지원합니다.

이 글은 Delphi teams adding certificate-based approval, invoice signing, or long-term validation evidence을 위한 글입니다. digital signatures and PAdES-ready signing을 단순한 컴포넌트 호출이 아니라 운영 환경의 문서 엔지니어링으로 다룹니다.

실제 위험은 a PDF may contain a visible signature box while the byte range, certificate chain, timestamp, revocation data, or later incremental update invalidates trust입니다. 따라서 명확한 계약, 관찰 가능한 진단, 실제 고객 파일을 반영한 회귀 샘플이 필요합니다.

아키텍처 결정

Design signing as a revision-controlled workflow. certificate source, private-key boundary, and operator approval process / timestamp authority, revocation source, and long-term validation profile

  • certificate source, private-key boundary, and operator approval process
  • timestamp authority, revocation source, and long-term validation profile
  • visible signature appearance, signer reason, contact, and location fields
  • whether later annotations, forms, or metadata updates are allowed after signing

구현 흐름

Prepare evidence before reserving the signature field. The order below keeps the workflow reviewable for Delphi and C++Builder teams.

  1. freeze the document content and preflight it before signature reservation
  2. load certificate material from the approved key store or signing service
  3. reserve the signature field and byte range with enough space for the final value
  4. apply timestamp and revocation data according to the selected PAdES profile
  5. verify the final file in at least one independent validator before release

검증 증거

Signature evidence worth keeping. Keep these fields with the output or support record.

  • signer certificate fingerprint, chain status, timestamp result, and revocation source
  • signature byte range, digest algorithm, PAdES profile, and validation summary
  • document hash before signing and final hash after the signed revision is saved
  • policy decision for any warning that did not block the signature

PAdES is a lifecycle, not only a signature

PAdES-ready output needs deterministic document bytes, a verified certificate context, timestamp policy, revocation evidence, and a save strategy that does not alter signed byte ranges after the signature is applied.

Profile ownership and versioning

A named, versioned profile is easier to review than options scattered across forms, scripts, and batch parameters. It also makes support reports readable when customers use older templates or policies.

  • certificate source, private-key boundary, and operator approval process
  • timestamp authority, revocation source, and long-term validation profile
  • visible signature appearance, signer reason, contact, and location fields
  • whether later annotations, forms, or metadata updates are allowed after signing
  • signer certificate fingerprint, chain status, timestamp result, and revocation source
  • signature byte range, digest algorithm, PAdES profile, and validation summary

digital signatures and PAdES-ready signing에 대한 엔지니어링 검토 노트

이 검토 노트를 사용해 기능이 데모 단계를 넘어섰고 출시, 지원, 고객 에스컬레이션 상황에서 설명할 수 있는지 확인합니다

  • 결정: certificate source, private-key boundary, and operator approval process. 구현상 핵심 지점: load certificate material from the approved key store or signing service. 승인 증거: document hash before signing and final hash after the signed revision is saved. 회귀 트리거: timestamp and revocation services need timeout and retry policies
  • 결정: timestamp authority, revocation source, and long-term validation profile. 구현상 핵심 지점: reserve the signature field and byte range with enough space for the final value. 승인 증거: policy decision for any warning that did not block the signature. 회귀 트리거: editing metadata or form values after signing can invalidate the signed revision
  • 결정: visible signature appearance, signer reason, contact, and location fields. 구현상 핵심 지점: apply timestamp and revocation data according to the selected PAdES profile. 승인 증거: signer certificate fingerprint, chain status, timestamp result, and revocation source. 회귀 트리거: certificate chain checks can pass on a developer machine but fail offline
  • 결정: whether later annotations, forms, or metadata updates are allowed after signing. 구현상 핵심 지점: verify the final file in at least one independent validator before release. 승인 증거: signature byte range, digest algorithm, PAdES profile, and validation summary. 회귀 트리거: visible appearance text should not be treated as cryptographic evidence
  • 결정: certificate source, private-key boundary, and operator approval process. 구현상 핵심 지점: freeze the document content and preflight it before signature reservation. 승인 증거: document hash before signing and final hash after the signed revision is saved. 회귀 트리거: timestamp and revocation services need timeout and retry policies

경계 사례

  • editing metadata or form values after signing can invalidate the signed revision
  • certificate chain checks can pass on a developer machine but fail offline
  • visible appearance text should not be treated as cryptographic evidence
  • timestamp and revocation services need timeout and retry policies

Delphi / C++Builder 참고 사항

HotPDF Component should sit behind a small service boundary that receives files, streams, profiles, and credentials, then returns output paths, warnings, metrics, and validation status. 중요한 용어는 PAdES, digital signature, byte range, timestamp, DSS, revocation.

Delphi 코드 예제

다음 Delphi 스케치는 이 주제에 맞는 실무형 서비스 경계를 보여 줍니다. 정책 검사, 로깅, 검증을 좁은 제품 호출 구간 밖에 두면 워크플로를 테스트하기 쉽습니다.

procedure SignApprovedPdf(const InputFile, OutputFile: string; const Policy: TSignaturePolicy);
var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    LoadUnsignedPackage(Pdf, InputFile);
    CheckSigningPolicy(Policy);
    AttachPadesEvidence(Pdf, Policy.Certificate, Policy.TimestampServer);
    SaveSignedPackage(Pdf, OutputFile);
    ValidateSignatureChain(OutputFile, Policy.TrustAnchors);
  finally
    Pdf.Free;
  end;
end;

운영 체크리스트

  • 워크플로는 빈 파일, 일반 고객 파일, 최악의 파일에서 실행합니다
  • 생성된 PDF는 대상 뷰어, 검증기, 프린터 또는 downstream 애플리케이션에서 엽니다
  • 제품 버전, 프로필 버전, 입력 해시, 출력 경로, 경과 시간, 경고 수를 기록합니다
  • 암호, 인증서, 임시 파일, 고객 데이터는 명확한 보존 규칙에 따라 관리합니다
  • 고객 파일이 새로운 경계 사례를 드러내면 회귀 문서를 추가합니다

제품 문서

HotPDF Component

추가 코드 예제

var
  Doc: THotPDF;
  Fs: TFileStream;
  PdfBytes, HashInput, SigHex: AnsiString;
  R1Start, R1Len, R2Start, R2Len, CStart, CLen: Integer;
begin
  // 1. Write the document with a reserved /Contents hole
  Doc := THotPDF.Create(nil);
  try
    Doc.FileName := 'placeholder.pdf';
    Doc.BeginDoc;
    Doc.CurrentPage.AddSignedSignatureField('Sig1',
      Rect(50, 100, 350, 150), 8192, 'adbe.pkcs7.detached',
      'Contract approval', 'Boston, MA', 'legal@example.com');
    Doc.EndDoc;
  finally
    Doc.Free;
  end;

  // 2. Load the saved bytes; the returned offsets are 0-based
  Fs := TFileStream.Create('placeholder.pdf', fmOpenRead);
  try
    SetLength(PdfBytes, Fs.Size);
    Fs.ReadBuffer(PdfBytes[1], Fs.Size);
  finally
    Fs.Free;
  end;
  THotPDF.PreparePDFForSigning(PdfBytes, R1Start, R1Len, R2Start, R2Len,
    CStart, CLen);

  // 3. Hash both spans and sign externally (HSM, token, service)
  HashInput := Copy(PdfBytes, R1Start + 1, R1Len) +
               Copy(PdfBytes, R2Start + 1, R2Len);
  SigHex := SignWithHsm(HashInput);  // your integration: returns CMS as hex

  // 4. Splice the signature into the reserved hole
  THotPDF.InsertSignatureHex(PdfBytes, SigHex);
  Fs := TFileStream.Create('signed.pdf', fmCreate);
  try
    Fs.WriteBuffer(PdfBytes[1], Length(PdfBytes));
  finally
    Fs.Free;
  end;
end;
// PAdES baseline signature field (ETSI EN 319 142-1)
Pdf.CurrentPage.AddPAdESSignatureField(
  'ApprovalSig', Rect(50, 100, 350, 150), 'B-B',
  'Contract approval', 'Boston, MA', 'legal@example.com');

// Document timestamp: larger reservation for the TSA token and chain
Pdf.CurrentPage.AddDocumentTimestampSignature('ArchiveTS', 16384);