Podpisz swój pierwszy dokument w 5 minut

Kompletny przewodnik od nowego projektu VCL do podpisanej koperty XAdES. Działa z Delphi 7 przez RAD Studio 13 i C++Builder.

Delphi 7 – RAD Studio 13
C++ Builder
VeriFactu Profile

Przed rozpoczęciem

Tylko dwie rzeczy — sgcSign zainstalowany w IDE i certyfikat PFX do podpisywania.

Będziesz potrzebować

  • Zainstalowany sgcSign w IDE — patrz strona pobierania.
  • Plik certyfikatu PFX z hasłem (działa dowolny plik X.509 PKCS#12).
  • Delphi 7 przez RAD Studio 13 lub dowolna wersja C++ Builder. Obsługiwane są zarówno 32-bitowy, jak i 64-bitowy system Windows.
  • Brak zewnętrznych zależności — sgcSign używa Windows CNG/BCrypt do kryptografii i WinHTTP do wywołań sieciowych.
make-test-cert.sh
# Brak PFX? Wygeneruj samopodpisany certyfikat testowy za pomocą OpenSSL:
openssl req -x509 -newkey rsa:2048 \
  -keyout key.pem -out cert.pem \
  -days 365 -nodes \
  -subj "/CN=sgcSign Test"

openssl pkcs12 -export \
  -inkey key.pem -in cert.pem \
  -out test.pfx \
  -password pass:secret

# Teraz masz plik test.pfx z hasłem "secret".

Utwórz nowy projekt

Utwórz aplikację VCL Forms w IDE. Upuść dwa pola memo i przycisk na formularz — to cały interfejs użytkownika.

Układ formularza

  • memoXMLTMemo, wklej tutaj niepodpisany XML.
  • memoSignedTMemo, po kliknięciu przycisku pojawi się tutaj podpisany XML.
  • btnSignTButton, podłączony do procedury obsługi OnClick w kroku 2.
  • Nie są wymagane komponenty czasu projektowania — wszystko jest tworzone w kodzie.
Unit1.dfm
object Form1: TForm1
  Caption = 'sgcSign Quick Start'
  ClientWidth  = 800
  ClientHeight = 600

  object memoXML: TMemo
    Left = 8
    Top  = 8
    Width  = 784
    Height = 240
  end

  object memoSigned: TMemo
    Left = 8
    Top  = 288
    Width  = 784
    Height = 300
  end

  object btnSign: TButton
    Left = 8
    Top  = 256
    Caption = 'Sign XML'
  end
end

Dodaj kod podpisywania

Załaduj dostawcę PFX, skieruj sygnatariusza dokumentu na niego z profilem VeriFactu i wywołaj SignXML.

Delphi

  • TsgcPFXKeyProvider importuje plik .pfx przez Windows CNG — nowoczesne podpisywanie SHA-256 działa niezależnie od oryginalnego CSP.
  • TsgcDocumentSigner wybiera właściwy poziom XAdES na podstawie profilu.
  • spVeriFactu wybiera hiszpański profil AEAT VeriFactu — XAdES-EPES, B-B, RSA-SHA256, wyłączna C14N.
  • Zamień stałą na dowolny z 21 profili krajowych — patrz Profile krajowe.
Unit1.pas
procedure TForm1.btnSignClick(Sender: TObject);
var
  vKeyProvider: TsgcPFXKeyProvider;
  vSigner: TsgcDocumentSigner;
begin
  vKeyProvider := TsgcPFXKeyProvider.Create(nil);
  try
    vKeyProvider.FileName := 'certificate.pfx';
    vKeyProvider.Password := 'secret';
    vKeyProvider.LoadFromFile;

    vSigner := TsgcDocumentSigner.Create(nil);
    try
      vSigner.KeyProvider := vKeyProvider;
      vSigner.Profile := spVeriFactu;
      memoSigned.Text := vSigner.SignXML(memoXML.Text);
    finally
      vSigner.Free;
    end;
  finally
    vKeyProvider.Free;
  end;
end;

C++ Builder

  • Taki sam kształt, te same klasy, te same nazwy właściwości — opakowanie C++ to port 1:1 API Delphi.
  • Blok __finally zapewnia zwolnienie dostawców nawet jeśli podpisywanie zgłosi wyjątek.
  • UnicodeString jest używany od początku do końca — nie trzeba się martwić o konwersję ANSI/UTF-8.
Unit1.cpp
void __fastcall TForm1::btnSignClick(TObject *Sender)
{
  TsgcPFXKeyProvider *vKeyProvider = new TsgcPFXKeyProvider(NULL);
  try {
    vKeyProvider->FileName = "certificate.pfx";
    vKeyProvider->Password = "secret";
    vKeyProvider->LoadFromFile();

    TsgcDocumentSigner *vSigner = new TsgcDocumentSigner(NULL);
    try {
      vSigner->KeyProvider = vKeyProvider;
      vSigner->Profile = spVeriFactu;
      memoSigned->Text = vSigner->SignXML(memoXML->Text);
    } __finally {
      delete vSigner;
    }
  } __finally {
    delete vKeyProvider;
  }
}

Dodaj wymagane jednostki

Dwie jednostki w klauzuli uses — dostawca PFX i sygnatariusz dokumentu.

Klauzula uses Delphi

Każdy dostawca kluczy ma własną jednostkę, więc płacisz tylko za to, do czego się odwołujesz. sgcSign_DocumentSigner wprowadza warstwę routingu, która wybiera XAdES, PAdES lub CAdES na podstawie danych wejściowych.

Unit1.pas
uses
  Classes, SysUtils, Forms, StdCtrls, Controls,
  // sgc
  sgcSign_KeyProvider_PFX,
  sgcSign_DocumentSigner;

Dołączenia C++ Builder

Te same jednostki, udostępnione jako nagłówki .hpp. Linker C++ Builder automatycznie rozwiązuje podległe biblioteki statyczne.

Unit1.cpp
#include "sgcSign_KeyProvider_PFX.hpp"
#include "sgcSign_DocumentSigner.hpp"

Uruchom i przetestuj

Naciśnij F9, wklej fakturę do górnego pola memo, kliknij Podpisz XML. Podpisana koperta pojawi się w dolnym polu memo.

Kompiluj i uruchom

Naciśnij F9 w IDE. Formularz otwiera się z dwoma polami memo i przyciskiem. Żadnych wyjątków, żadnych brakujących jednostek.

Wklej dane wejściowe

Wklej dowolny XML faktury (lub dowolny poprawnie sformułowany XML) do memoXML. Sygnatariusz normalizuje go wewnętrznie do UTF-8.

Sprawdź wynik

memoSigned zawiera teraz twój XML z dołączonym elementem <ds:Signature>. Zapisz go, uruchom przez dowolny weryfikator XAdES — lub bezpośrednio użyj TsgcSignatureVerifier.

Unicode i przeciążenie WideString

W Delphi 7 string to AnsiString. Używaj przeciążeń WideString do bezstratnego przetwarzania polskich, cyrylickich lub greckich znaków.

Pułapka

W Delphi 7 przeciążenie string kieruje przez systemowy ACP. Diacritics in 'Jarosław' only round-trip when the system ACP is CP1250. If the ACP is CP1252, characters get corrupted in the signed XML.

The WideString overloads bypass ACP entirely — UTF-16 to UTF-8 via WideCharToMultiByte with CP_UTF8. On Delphi 2009+ both overloads are equivalent; UnicodeString is already UTF-16.

d7-unicode.pas
var
  Doc: IXMLDocument;       // MSXML6
  XML, Signed: WideString; // = MSXML6 DOMString
  Sign: TsgcXAdESSigner;
begin
  Doc.SaveToXML(XML);            // WideString out, no ACP step
  Signed := Sign.SignXML(XML);   // resolves to WideString overload
  // Polish, Cyrillic, Greek round-trip losslessly
end;

UTC domyślnie

Wszystkie znaczniki czasu X.509 / CRL / OCSP / TSA są przechowywane jako wartości UTC TDateTime, zgodnie z leżącymi u podstaw specyfikacjami ASN.1.

Wyświetlanie w czasie lokalnym

W przypadku wyświetlania użytkownikom końcowym używaj właściwości *Local każdego komponentu (np. vCert.NotAfterLocal) lub konwertuj ręcznie za pomocą sgcUTCToLocal z jednostki sgcSign_Time.

Jest to zgodne z RFC 5280 (X.509), RFC 3161 (TSA) i RFC 6960 (OCSP), które wszystkie określają UTC. Pomocnik sgcUTCNow zwraca bieżące UTC TDateTime dla kodu, który musi porównywać znaczniki czasu.

time-zones.pas
uses sgcSign_Time;

// Display certificate validity in local time
Memo1.Lines.Add('Cert expires: ' +
                DateTimeToStr(vCert.NotAfterLocal));
Memo1.Lines.Add('Now (UTC):    ' +
                DateTimeToStr(sgcUTCNow));

// Or convert manually
vLocal := sgcUTCToLocal(vCert.NotAfter);

Co dalej

XAdES to dopiero początek. PAdES, CAdES, profile, dostawcy kluczy i scentralizowany serwer są o jedno kliknięcie dalej.

Przegląd funkcji

Przejdź przez pełną powierzchnię API XAdES, PAdES, CAdES i infrastrukturę znaczników czasu + OCSP.

Czytaj więcej →

21 profili krajowych

VeriFactu, FatturaPA, KSeF, FACTUR-X oraz 9 unijnych profili umów o pracę. Jednoliniowe przełączanie jurysdykcji.

Czytaj więcej →

10 dostawców kluczy

PFX, PEM, magazyn Windows, PKCS#11, Azure Trusted Signing, AWS KMS, Google KMS, Vault, Certum, CSC v2.

Czytaj więcej →

sgcSign Server

Scentralizuj podpisywanie na farmie budowania. REST API, panel administracyjny, GitHub Actions, Azure DevOps, Jenkins, Docker.

Czytaj więcej →

Gotowy na produkcję?

Pobierz wersję trial, dostarcz dzisiaj podpisany plik binarny, licencjonuj sgcSign gdy będziesz zadowolony.