Eğitim: Delphi'de PAdES PDF İmzalama

İmzalanmamış bir fatura PDF'ini alıp gömülü bir RFC 3161 zaman damgasıyla bir PAdES-B-T belgesi üreten eksiksiz bir adım adım kılavuz — eIDAS, AdES doğrulayıcıları ve çoğu kamu sektörü portalının beklediği düzey. Bir anahtar sağlayıcı (PKCS#11 akıllı kart veya Windows sertifika deposu) yapılandıracak, doğru PAdES profilini seçecek ve imzalı dosyayı uçtan uca doğrulayacaksınız.

PAdES-B-B / B-T / B-LT / B-LTA
PKCS#11 / Windows Deposu / PFX
Delphi 7 – RAD Studio 13

Ne oluşturacaksınız

Bir PDF yükleyen, onu bir akıllı kart veya PFX ile imzalayan, güvenilir bir zaman damgası gömen ve diske doğrulanabilir bir PAdES dosyası yazan bir VCL Forms uygulaması.

Bir PAdES düzeyi seçin

PAdES-B-B (temel), PAdES-B-T (zaman damgalı), PAdES-B-LT (iptal verileriyle uzun vadeli) veya PAdES-B-LTA (arşiv zaman damgasıyla uzun vadeli). PAdES-B-T; faturalar, sözleşmeler ve çoğu kamu sektörü iş akışı için mantıklı varsayılandır.

Bir anahtar yükleyin

sgcSign 10 anahtar sağlayıcıyı destekler. Bu eğitim, donanım belirteçleri için TsgcPKCS11KeyProvider ve Windows'a zaten yüklü sertifikalar için TsgcWindowsStoreKeyProvider kapsar. Aynı kod yolu PFX, PEM, Azure Trusted Signing, AWS KMS ve Google KMS için çalışır.

İmzalayın ve doğrulayın

TsgcSignPDF imzalama hattını yönlendirir, TsgcSignProfile_PAdES profili yapılandırır ve TsgcSignatureVerifier son belgeyi doğrular. Her adım olaylar sunar, böylece her aşamada neler olduğunu inceleyebilirsiniz.

Birimleri ekleyin

Her anahtar sağlayıcı kendi biriminde bulunur. Kullanmayacağınız birimleri bağlamamak için yalnızca ihtiyaç duyduğunuz sağlayıcıya başvurun.

Delphi uses cümlesi

Bu eğitim için iki anahtar sağlayıcı (PKCS#11 ve Windows Store) ile PAdES imzalama birimlerini ekliyoruz. sgcSign_TSA, RFC 3161 zaman damgası istemcisidir — PAdES profili, bir TSA URL'si ayarladığınızda bunu otomatik olarak kullanır.

Yalnızca bir PFX dosyanız varsa, sgcSign_KeyProvider_PKCS11'i sgcSign_KeyProvider_PFX ile değiştirin ve 5 dakikalık Hızlı Başlangıç'ta gösterildiği gibi TsgcPFXKeyProvider kullanın.

uPDFSigning.pas
uses
  Classes, SysUtils,
  // sgc
  sgcSign_KeyProvider_PKCS11,
  sgcSign_KeyProvider_WindowsStore,
  sgcSign_PDF,
  sgcSign_Profile_PAdES,
  sgcSign_TSA,
  sgcSign_Verifier;

Bir anahtar sağlayıcı yapılandırın

İki yaygın seçenek — bir PKCS#11 donanım belirteci (akıllı kartlar, USB HSM'ler) veya Windows sertifika deposunda zaten bulunan bir sertifika.

PKCS#11 akıllı kart

ModulePath'i sağlayıcının PKCS#11 DLL'sine yönlendirin (örneğin SafeNet için C:\Windows\System32\eTPKCS11.dll). Slot özelliği belirteç yuvasını seçer — ilk kullanılabilir belirteç için 0 kullanın. PIN, OnPinPrompt olayı aracılığıyla iletilir, böylece kaynakta asla saklanmaz.

LoadFromToken çağrısı bir oturum açar, imzalama sertifikasını etikete veya parmak izine göre bulur ve özel anahtar tutamacını hazırlar. Belirteçten hiçbir bayt çıkmaz — gerçek RSA-PSS veya ECDSA imzalama cihazda gerçekleşir.

step1-pkcs11.pas
var
  vKeyProvider: TsgcPKCS11KeyProvider;
begin
  vKeyProvider := TsgcPKCS11KeyProvider.Create(nil);
  try
    vKeyProvider.ModulePath := 'C:\Windows\System32\eTPKCS11.dll';
    vKeyProvider.Slot := 0;
    vKeyProvider.CertificateLabel := 'My Signing Cert';
    vKeyProvider.OnPinPrompt :=
      procedure(Sender: TObject; var aPIN: string)
      begin
        aPIN := InputBox('Smart card', 'PIN:', '');
      end;
    vKeyProvider.LoadFromToken;
    // vKeyProvider is now ready to sign
  finally
    // keep alive until signing finishes, then Free
  end;
end;

Windows sertifika deposu

Sertifikanız Windows deposuna zaten yüklüyse — örneğin bir sağlayıcı mini sürücüsüyle nitelikli bir eID kartı kullandığınız için — bunun yerine TsgcWindowsStoreKeyProvider kullanın. Sağlayıcı CNG ile konuşur, böylece SHA-256/SHA-384 orijinal CSP'den bağımsız olarak çalışır.

Konuya, parmak izine veya seri numarasına göre eşleştirin. StoreLocationslCurrentUser olarak ayarlamak kişisel depoyu kullanır; slLocalMachine makine deposunu kullanır ve genellikle yönetici hakları gerektirir.

step1-winstore.pas
var
  vKeyProvider: TsgcWindowsStoreKeyProvider;
begin
  vKeyProvider := TsgcWindowsStoreKeyProvider.Create(nil);
  vKeyProvider.StoreLocation := slCurrentUser;
  vKeyProvider.StoreName := 'MY';
  vKeyProvider.Thumbprint :=
    '1234ABCD5678EF901234567890ABCDEF12345678';
  vKeyProvider.LoadFromStore;
end;

PAdES-B-T profilini yapılandırın

PAdES-B-T, imzaya bir RFC 3161 zaman damgası ekler, böylece doğrulayıcılar belgenin bilinen bir zaman noktasından önce imzalandığını kanıtlayabilir — imzalama sertifikasının daha sonra süresi dolsa veya iptal edilse bile.

Profil özellikleri

Level, AdES düzeyini seçer — palB, palT, palLT veya palLTA. PAdES-B-T için bunu palT olarak ayarlayın; profil daha sonra boş olmayan bir TSA.URL bekler.

HashAlgorithm varsayılan olarak her modern doğrulayıcının beklediği shaSHA256'dır. SHA-384 ve SHA-512 de mevcuttur; eIDAS artık kabul etmediği için SHA-1 kasıtlı olarak sunulmaz.

SignatureField alt nesnesi, görünür imza pencere öğesinin PDF içinde nereye yerleştirileceğini denetler — sayfa numarası, dikdörtgen koordinatları ve isteğe bağlı sebep / konum / iletişim metin alanları. Görünmez imzalar için boş bırakın (varsayılan).

step2-profile.pas
var
  vProfile: TsgcSignProfile_PAdES;
begin
  vProfile := TsgcSignProfile_PAdES.Create(nil);
  vProfile.Level := palT;
  vProfile.HashAlgorithm := shaSHA256;

  // RFC 3161 timestamp authority
  vProfile.TSA.URL := 'http://timestamp.digicert.com';
  vProfile.TSA.HashAlgorithm := shaSHA256;

  // Optional visible signature widget
  vProfile.SignatureField.Visible := True;
  vProfile.SignatureField.Page := 1;
  vProfile.SignatureField.Rect := Rect(50, 50, 250, 120);
  vProfile.SignatureField.Reason := 'Approved';
  vProfile.SignatureField.Location := 'Madrid';
end;

PDF'i imzalayın

Anahtar sağlayıcıyı ve profili TsgcSignPDF'e bağlayın, ardından giriş ve çıkış dosya adlarıyla SignFile çağırın.

Tam imzalama çağrısı

SignFile giriş PDF'ini okur, belge özetini hesaplar, bir imza üretmek için anahtar sağlayıcıyı çağırır, TSA'dan bir zaman damgası getirir ve sonucu yazar. Giriş zaten imzalar içeriyorsa, sgcSign artımlı bir güncelleme ekler — orijinal imzalar geçerli kalır.

OnProgress olayı her aşamayı bildirir (okuma, karma, imzalama, zaman damgalama, yazma), çok megabaytlık dosyalarda ilerleme çubukları için yararlıdır.

step3-sign.pas
var
  vSigner: TsgcSignPDF;
begin
  vSigner := TsgcSignPDF.Create(nil);
  try
    vSigner.KeyProvider := vKeyProvider;
    vSigner.Profile := vProfile;
    vSigner.OnProgress :=
      procedure(Sender: TObject; const aPhase: string; aPct: Integer)
      begin
        Memo1.Lines.Add(Format('%s — %d%%', [aPhase, aPct]));
      end;
    vSigner.SignFile('invoice.pdf', 'invoice-signed.pdf');
  finally
    vSigner.Free;
  end;
end;

İmzalı PDF'i doğrulayın

İmzalı bir belge yalnızca doğrulanırsa yararlıdır. TsgcSignatureVerifier, kriptografik imzayı, sertifika zincirini ve gömülü zaman damgasını tek bir çağrıda doğrular.

Sonucu okuma

VerifyFile metodu, imza başına bir döküm içeren bir TsgcSignatureReport döndürür. Her giriş için Status (svValid, svInvalid, svUnknown), imzalayan konusu, gerçekte algılanan AdES düzeyi, zaman damgası değeri ve herhangi bir zincir veya iptal sorunu elde edersiniz.

Report.Level'i beklediğiniz düzeyle karşılaştırın — palT istediniz, bu nedenle palB bildiren herhangi bir doğrulama, zaman damgası isteğinin sessizce başarısız olduğu anlamına gelir. TSA URL'si her zamanki şüphelidir.

step4-verify.pas
var
  vVerifier: TsgcSignatureVerifier;
  vReport: TsgcSignatureReport;
  i: Integer;
begin
  vVerifier := TsgcSignatureVerifier.Create(nil);
  try
    vReport := vVerifier.VerifyFile('invoice-signed.pdf');
    for i := 0 to vReport.SignatureCount - 1 do
    begin
      Memo1.Lines.Add('Signer:    ' + vReport.Signatures[i].Subject);
      Memo1.Lines.Add('Level:     ' + vReport.Signatures[i].LevelAsString);
      Memo1.Lines.Add('Status:    ' + vReport.Signatures[i].StatusAsString);
      Memo1.Lines.Add('TSA time:  ' +
        DateTimeToStr(vReport.Signatures[i].TimestampUTC));
    end;
  finally
    vVerifier.Free;
  end;
end;

Genellikle ne ters gider

Geliştiriciler ilk PAdES belgelerini imzaladığında en sık gördüğümüz sorunların kısa bir listesi.

TSA, HTTP 200 döndürür ancak hatalı biçimlendirilmiş bir yanıt

Bazı TSA'lar yalnızca HTTPS'dir ve düz http:// URL'lerini yumuşak bir hatayla reddeder. palT istediğinizde Report.Level palB olarak geri gelirse, TSA URL'sini https:// eşdeğerine değiştirin. Çoğu herkese açık TSA her iki şemayı da yayınlar.

Sertifikanın genişletilmiş anahtar kullanımı yok

Test sertifikalarında genellikle id-kp-documentSigning EKU'su eksiktir. Adobe Reader, kriptografik imza geçerli olsa bile bir uyarı görüntüler. Üretim için CA'nızdan açık Document Signing EKU'lu bir sertifika isteyin.

PDF/A belgeleri PAdES-B-LT gerektirir

PDF/A-2 ve PDF/A-3 arşivleri, tüm iptal bilgilerinin belgenin kendisine gömülmesini gerektirir. palLT veya palLTA kullanın — sgcSign, imzalama sırasında OCSP yanıtlarını ve CRL'leri toplar ve bunları DSS sözlüğüne gömer.

Akıllı kart oturumlarının zaman aşımına uğraması

Bazı PKCS#11 sürücüleri, birkaç saniyelik hareketsizlikten sonra oturumu kapatır. TsgcPKCS11KeyProvider örneğini tüm imzalama işlemi boyunca canlı tutun ve Free'yi yalnızca SignFile döndükten sonra çağırın.

Buradan nereye gidilir

Uzun vadeli arşivleme, ülke profilleri veya imzalamayı masaüstünden alıp merkezi bir sunucuya taşıma.

21 Ülke Profili

VeriFactu, FatturaPA, KSeF, FACTUR-X ve AB iş sözleşmesi profilleri için tek satırlık kodlar — tümü aynı PAdES / XAdES motorunun üzerine kurulmuştur.

Devamını okuyun →

sgcSign Server

İmzalamayı kendi sunucunuzda barındırılan bir hizmete taşıyın — REST API, GitHub Actions entegrasyonu, PAdES'in üzerine Authenticode ve ClickOnce.

Devamını okuyun →

10 Anahtar Sağlayıcı

PFX ve Windows deposunun ötesinde — Azure Trusted Signing, AWS KMS, Google KMS, HashiCorp Vault, Certum ve CSC v2 bulut sağlayıcıları.

Devamını okuyun →

İlk PDF'inizi imzalamaya hazır mısınız?

Denemeyi indirin, bu eğitimi kendi faturanız üzerinde çalıştırın, yayınladığınızda sgcSign'i lisanslayın.