Teknik Makale

Delphi'de HotPDF ile Kuantum-Sonrası ve EdDSA PDF İmzalama

HotPDF, yüklenen PDF belgelerinde ML-DSA-44, ML-DSA-65, ML-DSA-87, Ed25519 ve Ed448 CMS imzalarını doğrular ve özel anahtarın Delphi süreciniz içinde yaşaması gerekmediği şekilde, eklenebilen sağlayıcılar üzerinden imzalar. İkinci yarı, çoğu ekibin önce ihtiyaç duyduğu kısımdır. Bir donanım belirteci, uzak bir imzalama hizmeti ve ulusal bir eID kartının hepsi anahtarı teslim etmeyi reddeder ve imzalama akışı anahtar deposundan ayrılana dek hiçbiri kullanılamaz

Bu ayrım, THPDFSignatureProvider'ın nedenidir. HotPDF sahibi olması gereken kısımları tutar; CMS'i ayrıştırmak, SignedData inşa etmek, /ByteRange'i yerleştirmek ve sahibi olamayacağı tek işlemi, yani görmesine izin verilmeyen bir anahtarla bir özeti imzaya dönüştürmeyi devreder. Aşağıdaki her şey bu bölüştürmeden doğar

Geçerli bir ML-DSA imzası neden doğrulanamıyor?

Çünkü HotPDF, onun için uzantıyı bildirmeyen yüklenmiş bir belgede ML-DSA'yı reddeder. ML-DSA, FIPS 204 olarak standartlaştırılmış kafes imza şeması ve insanların "kuantum-sonrası PDF" dediği neden, henüz bir ISO 32000-2 kaydına sahip değildir. Bir tane taşıyan PDF, temel standardın adlandırmadığı bir algoritma kullanıyor demektir ve sessizce adlandırılmamış bir algoritma kullanan bir dosya, karardan başka kimsenin yeniden üretemeyeceği bir dosyadır

Dolayısıyla HotPDF iddiayı açık hâle getirir. EnsureMLDSAExtensions, belgeyi izin verildiğinde PDF 2.0'a yükseltir ve Kataloğa /Extensions /HotPDF << /BaseVersion /2.0 /ExtensionLevel 1 >> yazar. Okuma tarafında LoadedDocumentDeclaresMLDSAExtension, o bildirimin hayatta kaldığını raporlar ve VerifyLoadedSignatureWithOptions, Options.AllowMLDSA'ya saygı göstermeden önce aynı testi uygular. Bayrağı bildirilmemiş bir belgede açın ve kapalı kalır; seçenek politikayı gevşetebilir, yapısal gereksinimi asla

var
  Pdf: THotPDF;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := 'contract-pq.pdf';
    Pdf.BeginDoc;
    Pdf.CurrentPage.SetFont('Arial', [], 11);
    Pdf.CurrentPage.TextOut(50, 720, 0, 'Supply agreement 2026-114');
    Pdf.EnsureMLDSAExtensions;   // declare before the signature is written
    Pdf.EndDoc;
  finally
    Pdf.Free;
  end;
end;

Kaydettikten sonra değil, önce çağırın. Bildirim imzalı byte aralığının parçasıdır ve sonradan yamalanmış bir Katalog ya imzalı bir dosyada imzalanmamış bir değişikliktir ya da bir doğrulayıcının değişiklik olarak raporlayacağı ikinci bir revizyon

Üç algoritma ailesi, tek doğrulama giriş noktası

Üç ailenin tamamı, bir imza indeksi, kaynak akış, bir THPDFCMSVerifyOptions kaydı ve imza ayrıntıları için bir out parametresi alan VerifyLoadedSignatureWithOptions üzerinden gelir. Kaydın tam olarak üç alanı vardır ve her biri eskiden bir yeniden derleme gerektiren bir soruyu yanıtlar

SignatureProvider, yerleşik platform sağlayıcısı yerine kendi sağlayıcınızı koyar. OpenSSLLibraryPath bir OpenSSL 3 kitaplığı seçer; Windows CNG'nin her yerde sunmadığı saf mod Ed25519 ve Ed448 doğrulamasını sağlayan da budur. AllowMLDSA, yukarıdaki uzantı denetimine bağlı olarak kafes algoritmalarına izin verir. Tanınan tam algoritma OID'i THPDFSignatureInfo.SignatureAlgorithmOID olarak geri döner, dolayısıyla bir denetim günlüğü istenen değil doğrulanan şeyi kaydedebilir

var
  Opts: THPDFCMSVerifyOptions;
  Info: THPDFSignatureInfo;
  Status: THPDFSignatureVerifyStatus;
  Src: TFileStream;
begin
  Opts := THPDFCMSVerifyOptions.Default;
  Opts.OpenSSLLibraryPath := 'C:\openssl3\libcrypto-3-x64.dll';
  Opts.AllowMLDSA := Pdf.LoadedDocumentDeclaresMLDSAExtension;
  Src := TFileStream.Create('contract-pq.pdf', fmOpenRead or fmShareDenyWrite);
  try
    Status := Pdf.VerifyLoadedSignatureWithOptions(0, Src, Opts, Info);
    if Status = svValid then
      Memo1.Lines.Add('signed with OID ' + string(Info.SignatureAlgorithmOID));
  finally
    Src.Free;
  end;
end;

Ed25519 ve Ed448 uzantı bildirimi gerektirmez, çünkü ISO 32000-2 zaten onları kabul eder. Yalnızca onları uygulayan bir sağlayıcıya ihtiyaç duyarlar; çoğu Windows dağıtımında bu, makinede ne tesadüfen varsa ona değil, sizin dağıttığınız ve denetlediğiniz bir kitaplığa OpenSSLLibraryPath'i işaret etmek anlamına gelir

Bir imzalama sağlayıcısı aslında ne vaat eder?

Bir sağlayıcı tek bir şey vaat eder: kendisine bir istek verildiğinde, bir durum ve imzalıyorsanız byte döndürür. THPDFSignatureProviderRequest, algoritmayı ve OID'ini, özet OID'ini, PSS tuz uzunluğunu, girdinin bir ileti mi yoksa önceden hesaplanmış bir özet mi olduğunu, girdinin kendisini, genel anahtarı veya sertifikayı, bir anahtar tanımlayıcıyı ve bir işlem tanımlayıcıyı taşır. Bu kayıttaki hiçbir şey HotPDF'e özel değildir; bir belirteç sürücüsünün veya imzalama hizmetinin zaten konuştuğu kelime dağarcığıdır

Kitaplıkla birlikte üç uygulama gelir. THPDFCallbackSignatureProvider anonim yöntemleri sarar; var olan şirket içi bir imzalama yordamından çalışan bir PDF imzasına giden en kısa yoldur. THPDFRemoteSignatureProvider bir taşıma geri çağırmasını yeniden deneme sınırı, iptal kaydı ve girdi ve imza boyutu sınırlarıyla sarar, dolayısıyla yanıt vermeyen bir HSM yanıt vermeyen bir uygulamaya dönüşemez. THPDFPKCS11SignatureProvider, çağıranın sahip olduğu, önceden doğrulanmış bir PKCS#11 oturumu ve özel anahtar tanıtıcısına karşı RSA işlemlerini serileştirir; HotPDF asla oturum açmaz, PIN görmez ve açmadığı bir oturumu asla kapatmaz

var
  Provider: THPDFRemoteSignatureProvider;
begin
  Provider := THPDFRemoteSignatureProvider.Create(
    function(const Req: THPDFSignatureProviderRequest; Attempt: Integer;
      out Signature: TBytes): THPDFSignatureProviderStatus
    begin
      // POST Req.Input to the signing service; Req.KeyIdentifier selects the key
      if PostToSigningService(Req.KeyIdentifier, Req.Input, Signature) then
        Result := spsValid
      else
        Result := spsProviderError;
    end,
    3,          // RetryLimit
    1048576,    // MaxInputBytes
    65536);     // MaxSignatureBytes
  try
    // hand Provider to the signing call
  finally
    Provider.Free;
  end;
end;

Durum sabit listesinin bir boolean yerine altı değeri neden var?

THPDFSignatureProviderStatus, spsValid, spsInvalid, spsUnsupported, spsMalformed, spsProviderError ve spsCancelled değerlerini birbirinden ayırır ve bunları daraltmak doğru davranma yeteneğinizi elinizden alır. Kriptografik olarak yanlış olan bir imza (spsInvalid) bir güvenlik olayıdır. Sağlayıcının uygulamadığı bir algoritma (spsUnsupported) bir dağıtım boşluğudur. Bir taşıma hatası (spsProviderError) yeniden denemeye değerdir ve kullanıcı tarafından iptal edilmiş bir belirteç istemi (spsCancelled) hiç yeniden denemeye değmez

İmzalama kuralı dardır: bir imzalama sağlayıcısı spsValid'i yalnızca boş olmayan bir imzayla döndürür. Doğrulama sağlayıcıları spsValid veya spsInvalid döndürür ve diğer dört değer her iki yolda da ayrı kalır. Bir sağlayıcı yazıyorsanız, tanımadığınız her şeyi spsInvalid'a eşlemenin cazibesine direnin; bu, eksik bir DLL'i müşterinin imzasının sahte olduğuna dair bir rapora dönüştürür

İmza dosyada gerçekte nereye düşer?

İki işlev sağlayıcıları gerçek PDF byte'larına bağlar. HPDFCMSBuildSignedDataWithProvider bir belge SHA-256 özetinden ayrık CMS inşa eder; iş akışınız özeti başka yerde hesapladığında doğru giriş noktası budur. HPDFCMSSignPDFStreamWithProvider, bir PDF akışında var olan bir imza yer tutucusunu imzalar ve standart /ByteRange akışını korur; HotPDF yer tutucuyu kendisi yerleştirdiğinde doğru giriş noktası budur

Bu akışı korumak kulağa geldiğinden daha fazla önem taşır. /ByteRange kuralı (onaltılık imza penceresini atlayan iki aralık), her doğrulayıcının önce denetlediği şeydir ve onu yeniden yazan sağlayıcı tabanlı bir yol, kriptografi ne kadar sağlıklı olursa olsun PAdES uyumluluğunu bozardı. HotPDF yerleşimi yerleşik imzalama yoluyla özdeş tutar, dolayısıyla bir PKCS#11 belirteci üzerinden imzalanmış bir belge, bir PFX dosyasından imzalanmış bir belgeyle aynı imza doğrulama koduyla doğrulanır. Algoritma seçiminin üzerindeki profil kuralları için Delphi'de PAdES temel imzaları yazısına ve bu sağlayıcı modelinden önce gelen ECDSA'ya özgü kodlama tuzakları için ECDSA CMS doğrulaması ve P1363 imza biçimleri notlarına bakın

Belgelerinizi yarı yolda bırakmayan bir geçiş sırası

Kuantum-sonrası hazır olma bir anahtar değil, bir takvim sorunudur. Yığındaki hemen hemen hiçbir PDF görüntüleyici bugün ML-DSA doğrulamaz, dolayısıyla yalnızca onunla imzalanmış bir belge, okuyucunun bakış açısından doğrulanamaz bir imzaya sahip bir belgedir. Gerçek arşivlerle karşılaşınca hayatta kalacak sıra şudur: bir doğrulayıcının yargılayacağı imza olarak RSA veya ECDSA'yı tutun, bir politika kuantum dirençli kanıt talep ettiğinde uzantı bildirimini ve ikinci bir ML-DSA imzasını ekleyin ve birincil imzayı yalnızca tüketen sistemler yetiştiğinde taşıyın

HotPDF'in bugün size verdiği şey, her ikisini de aynı koddan, algoritmanın dosyada ve doğrulama sonucunda dürüstçe kaydedilmesiyle yazma ve doğrulama yeteneğidir. HotPDF, Delphi ve C++Builder için harici bir PDF çalışma zamanı olmaksızın yerel bir VCL PDF bileşenidir, dolayısıyla imzalama ve doğrulama yolları uygulamanızın yanında değil içine derlenir; tam özellik listesi ve deneme indirmesi için HotPDF Delphi PDF bileşeni sayfasına bakın