sgcSign in vijf minuten

Twee componenten ondertekenen een document: een ondertekenaar en een sleutelprovider. Deze pagina ondertekent een PDF met PAdES, met een certificaat uit het Windows-certificaatarchief, en laat daarna zien hoe je verifieert wat je hebt gemaakt. Als je liever XML ondertekent, is er hieronder een uitgebreidere XAdES-uitleg gelinkt.

PAdES, XAdES, CAdES, ASiC
Tien sleutelproviders, van PFX tot cloud-HSM
Windows, Win32 en Win64

Een ondertekenaar en een sleutelprovider

De ondertekenaar kent het documentformaat. De sleutelprovider weet waar de privésleutel staat. Ze ontmoeten elkaar op één eigenschap.

De ondertekenaar

TsgcPAdESSigner, gedeclareerd in sgcSign_PAdES.pas en geregistreerd op de palettabpagina SGC Sign. SignPDFFile neemt een invoerpad en een uitvoerpad.

De sleutelprovider

TsgcWindowsCertStoreProvider voor het Windows-certificaatarchief, of TsgcPFXKeyProvider voor een .pfx-bestand. Beide staan op dezelfde palettabpagina.

De eigenschap die ze verbindt

KeyProvider, waarvan het type de interface IsgcKeyProvider is in plaats van een componentreferentie. Dat onderscheid is belangrijk voor de levensduur en het gedeelte over valkuilen hieronder legt uit waarom.

Platform

Win32, Win64, Linux64, macOS op Intel en Apple Silicon, iOS en Android. Op Windows lopen hashing en ondertekenen via de Windows CNG-API, op elk ander platform via de eigen pure Pascal-cryptografie van de bibliotheek, zonder OpenSSL om mee te leveren. De provider voor het Windows-certificaatarchief is het enige component dat alleen voor Windows blijft.

Vereisten en edities

sgcSign heeft geen functieniveaus, dus deze tabel gaat over compilers en platforms in plaats van edities.

Onderdeel Waarde
IDE Delphi 7 tot en met RAD Studio 13 en C++Builder. Bij C++Builder komt de libmap op het System Include-pad in plaats van het bibliotheekpad.
Uses-clausule De demo schrijft sgcSign_Types, sgcSign_Interfaces, sgcSign_Classes, sgcSign_PAdES, sgcSign_KeyProvider_WinCertStore, sgcSign_KeyProvider_PEM, sgcSign_KeyProvider_PFX. Laat de providers weg die je niet gebruikt.
Edities Die zijn er niet. De eigen sgcVer.inc van het product bevat helemaal geen SGC_EDT_*-define en geen enkele functie wordt per niveau afgeschermd. Eén bibliotheek, elk component, in elke licentie. De commerciële niveaus zijn gebaseerd op het aantal gebruikers: Single, Team en Site, plus een gratis Community Edition.
Platform, gecontroleerd in de broncode Win32, Win64, Linux64, OSX64, OSXARM64, iOS en Android. De cryptografie loopt via één naadunit, sgcSign_Crypto.pas, die CNG is op Windows en overal elders pure Pascal. HTTP is WinHTTP op Windows en elders de Delphi RTL-client. De runtime-packages schakelen Linux64 en macOS op Intel in vanaf Delphi 10.3, Android en iOS vanaf 10.4 en macOS op Apple Silicon vanaf 11. sgcSign_KeyProvider_WinCertStore.pas is de enige unit die alleen voor Windows is.
Externe afhankelijkheden Geen. Op Windows roept de bibliotheek de Windows CNG- en WinHTTP-API's rechtstreeks aan en op de andere platforms gebruikt ze de eigen pure Pascal-cryptografie en de Delphi RTL HTTP-client, dus er zijn geen OpenSSL-DLL's om met je toepassing mee te leveren.
Standaardwaarden Een nieuwe TsgcPAdESSigner heeft al een bruikbaar profiel: de constructor stelt het basis-PAdES-profiel, het baseline B-handtekeningniveau en SHA-256 in. Je hoeft Profile niet aan te raken om een geldige handtekening te maken.

Liever XML dan PDF? De XAdES-uitleg van vijf minuten ondertekent in plaats daarvan een XML-document met een PFX-bestand en behandelt de Unicode-valkuil van Delphi 7 en de UTC-ondertekeningstijd. Deze pagina is het PDF- en certificaatarchief-equivalent.

Installeer en vind de palettabpagina

Compileer het runtime-package voordat je het designtime-package installeert, want het tweede verwijst naar het eerste.

1. Uitpakken

Pak de download uit in een map, hieronder {$DIR} genoemd.

2. Bibliotheekpad

Tools, Environment Options, Directories. Voeg {$DIR}\delphi\source toe, wat voor elke RAD Studio-versie geldt.

3. De libmap toevoegen

Voeg ook de versiespecifieke map toe, bijvoorbeeld {$DIR}\delphi\libD13\$(Platform) op RAD Studio 13, tot libD7 op Delphi 7. Voor C++Builder komen deze in plaats daarvan op het System Include-pad.

4. De packages bouwen

Open Packages\sgcSignD13.groupproj voor jouw IDE-versie, of sgcSignC13.groupproj voor C++Builder. Compileer eerst het package sgcSign en installeer daarna dclsgcSign.

5. Het palet controleren

Er verschijnt een pagina met de naam SGC Sign met de ondertekenaars, de verifier, de timestamp- en OCSP-clients en de tien sleutelproviders. Op Windows bevat die ook de Authenticode-ondertekenaar en -verifier.

Onderteken een PDF, in ongeveer twintig regels

Kies een certificaat, maak de ondertekenaar aan, wijs die naar de provider en roep SignPDFFile aan. Het eerste tabblad gebruikt het Windows-certificaatarchief, het tweede een PFX-bestand.

frmMain.pas
uses
  SysUtils, Classes,
  // sgcSign
  sgcSign_Types, sgcSign_Interfaces, sgcSign_Classes,
  sgcSign_PAdES, sgcSign_KeyProvider_WinCertStore;

procedure TFormMain.btnSignClick(Sender: TObject);
var
  vSigner: TsgcPAdESSigner;
  vKeyProvider: TsgcWindowsCertStoreProvider;
  vProviderIntf: IsgcKeyProvider;
  vOutputFile: string;
begin
  vKeyProvider := TsgcWindowsCertStoreProvider.Create(nil);
  vSigner := TsgcPAdESSigner.Create(nil);
  try
    vKeyProvider.SelectCertificateBySubject('My Company');
    Log('Certificate found: ' + vKeyProvider.Certificate.Subject);

    // Hold the interface in an explicit local: an inline "as" cast
    // would leave a compiler-generated interface temporary alive in
    // this stack frame until the routine returns, i.e. past
    // vKeyProvider.Free, and releasing it would touch freed memory.
    vProviderIntf := vKeyProvider as IsgcKeyProvider;
    vSigner.KeyProvider := vProviderIntf;
    vSigner.Reason := 'Demo signature';
    vSigner.Location := 'Spain';
    vSigner.SignerName := 'sgcSign Demo';

    vOutputFile := ChangeFileExt(edInputFile.Text, '_signed.pdf');
    vSigner.SignPDFFile(edInputFile.Text, vOutputFile);

    Log('SUCCESS: PDF signed with PAdES profile');
    Log('Output file: ' + vOutputFile);
  finally
    vSigner.Free;
    vProviderIntf := nil;
    vKeyProvider.Free;
  end;
end;

Let op wat hier niet staat. Profile wordt nooit aangeraakt, omdat de constructor al een basis-PAdES-profiel, het baseline B-handtekeningniveau en SHA-256 instelt. De opmerking over de tijdelijke interface is van de meegeleverde demo zelf en de vrijgavevolgorde in het finally-blok is de reden dat het ertoe doet.

frmMain.pas
uses
  SysUtils, Classes,
  // sgcSign
  sgcSign_Types, sgcSign_Interfaces, sgcSign_Classes,
  sgcSign_PAdES, sgcSign_KeyProvider_PFX;

var
  vSigner: TsgcPAdESSigner;
  vKeyProvider: TsgcPFXKeyProvider;
  vProviderIntf: IsgcKeyProvider;
begin
  vKeyProvider := TsgcPFXKeyProvider.Create(nil);
  vSigner := TsgcPAdESSigner.Create(nil);
  try
    vKeyProvider.FileName := 'C:\certs\signer.pfx';
    vKeyProvider.Password := GetPfxPassword;
    vKeyProvider.LoadFromFile;
    Log('Certificate loaded (PFX): ' + vKeyProvider.Certificate.Subject);

    vProviderIntf := vKeyProvider as IsgcKeyProvider;
    vSigner.KeyProvider := vProviderIntf;

    vSigner.SignPDFFile('C:\docs\contract.pdf',
      'C:\docs\contract_signed.pdf');
  finally
    vSigner.Free;
    vProviderIntf := nil;
    vKeyProvider.Free;
  end;
end;

Het enige verschil met het eerste tabblad is welke provider je aanmaakt en hoe je die naar een sleutel wijst. Alles vanaf KeyProvider := is identiek, en dat geldt voor alle tien de providers, inclusief PKCS#11-hardware en de cloudsleuteldiensten.

uVerify.pas
uses
  SysUtils, Classes,
  // sgcSign
  sgcSign_Types, sgcSign_Interfaces, sgcSign_Verifier;

var
  oVerifier: TsgcSignatureVerifier;
  vVerifier: IsgcSignatureVerifier;
  oStream: TFileStream;
begin
  oVerifier := TsgcSignatureVerifier.Create(nil);
  oStream := TFileStream.Create('C:\docs\contract_signed.pdf',
    fmOpenRead or fmShareDenyWrite);
  try
    // VerifyPDF is reached through the interface the component implements
    vVerifier := oVerifier as IsgcSignatureVerifier;

    if vVerifier.VerifyPDF(oStream) = vsValid then
      Writeln('valid')
    else
      Writeln(oVerifier.GetVerificationDetails);
  finally
    vVerifier := nil;
    oStream.Free;
    oVerifier.Free;
  end;
end;

Dezelfde interfaceregel als bij de ondertekenaar: wijs de cast toe aan een benoemde lokale variabele en wis die voordat je het component vrijgeeft. GetValidationReportXML maakt een rapport in het ETSI-validatierapportformaat wanneer een boolean niet genoeg bewijs is.

De eerste twee tabbladen komen uit de meegeleverde demo Demos\Delphi\PAdES\frmMain.pas, met de vertakkingen samengevoegd tot één pad per tabblad. De opmerking over het bewaren van de interface in een benoemde lokale variabele is van de demo zelf en het is de moeite waard die te behouden. Een rijkere zusterdemo, Demos\Delphi\PAdES_Providers, doet hetzelfde met hardware- en cloudproviders.

Controleer de handtekening, kijk niet alleen naar het bestand

Er is een bestand verschenen. Dat is niet hetzelfde als een handtekening die valideert.

Het certificaat is gevonden

Lees Certificate.Subject na het selecteren, zoals de demo doet. Het is het verschil tussen ondertekenen met het certificaat dat je bedoelde en ondertekenen met het certificaat dat het eerst overeenkwam. IsLoaded beantwoordt dezelfde vraag als boolean.

Het bestand is verschenen

SignPDFFile schrijft naar het uitvoerpad dat je hebt opgegeven. De meegeleverde demo leidt het af met ChangeFileExt, zodat het ondertekende bestand naast het origineel terechtkomt.

Het veroorzaakt een exception, het geeft geen code terug

Er is geen resultaat om te testen, dus plaats de aanroep in een try except en lees de exceptionmelding. Dat doet de demo en het is het enige foutkanaal.

De handtekening valideert

Een bestand is geen geldige handtekening. TsgcSignatureVerifier.VerifyPDF geeft een TsgcVerificationStatus terug die je vergelijkt met vsValid en GetVerificationDetails verklaart een fout. Het bestand openen in een PDF-lezer toont hetzelfde aan een persoon.

Wat er de eerste keer meestal misgaat

Zes problemen verklaren bijna elke eerste handtekening.

Een access violation bij het afsluiten

Dit is degene waarvoor de demo in zijn eigen opmerking waarschuwt. KeyProvider neemt een IsgcKeyProvider, dus een inline as-cast laat een door de compiler gegenereerde interfacereferentie in leven tot de routine terugkeert, en dat is nadat je het providercomponent hebt vrijgegeven. Wijs de interface toe aan een benoemde lokale variabele en geef vrij in de volgorde: ondertekenaar, daarna interface op nil, daarna provider.

Profile is geen string

Het is een TsgcSignProfileConfig-object. Je stelt Profile.Profile en Profile.SignatureLevel in, niet Profile := 'something'. De constructor vult al een bruikbare standaardwaarde in, dus het eerste voorbeeld hoeft het helemaal niet aan te raken.

Er wordt geen certificaat gevonden

SelectCertificateBySubject komt overeen op het onderwerp en SelectCertificateByThumbprint op de vingerafdruk. Lees Certificate.Subject na het selecteren, zoals de demo doet, zodat je kunt zien welk certificaat je echt hebt gekregen. EnumerateCertificates toont wat beschikbaar is.

Het compileert niet buiten Windows

Dat kan niet. De ondertekenaar en elke provider zetten Windows zonder voorwaarde in de interface-uses-clausule, dus dit is een compilerfout in plaats van een lege unit. sgcSign is een Windows-bibliotheek.

De handtekening wordt in de lezer als onbekend getoond

Een basishandtekening bevat geen trust anchor en geen intrekkingsgegevens. Voeg een timestamp toe via TSAClient en stap over op een langetermijnprofiel wanneer het document verifieerbaar moet blijven nadat het certificaat is verlopen.

SignPDFFile veroorzaakt een exception in plaats van een code terug te geven

Dat is zo ontworpen. Er is geen retourwaarde om te testen, dus plaats de aanroep in een try except en lees de exceptionmelding, wat de meegeleverde demo doet.

Voorbij de eerste handtekening

Vier richtingen, allemaal binnen dezelfde bibliotheek.

Andere documentformaten

XAdES en XMLDSig voor XML, CAdES voor detached CMS, ASiC-containers en speciale ondertekenaars voor ClickOnce-, NuGet- en VSIX-packages. Op Windows is er ook een Authenticode-ondertekenaar.

Alle sgcSign-componenten

Waar de sleutel staat

Er worden tien sleutelproviders meegeleverd: PFX, PEM, het Windows-archief, PKCS#11-hardware, Azure Trusted Signing, AWS KMS, Google Cloud KMS, Certum SimplySign, HashiCorp Vault en het CSC-protocol voor ondertekenen op afstand.

Sleutelproviders

Landprofielen

Eenentwintig land- en sectorprofielen, van het Spaanse VeriFactu tot de EU-factuurformaten, elk met de velden en het handtekeningniveau dat dat regime verwacht.

Handtekeningprofielen

Onderteken ergens anders

sgcSign Server is een zelf gehoste daemon die de sleutels beheert en op verzoek ondertekent, zodat het certificaat nooit de machine verlaat die je ermee vertrouwt.

sgcSign Server

Referentie, demo's en documentatie

Demoprojecten zitten in de download, onder Demos\Delphi. De PAdES-demo is degene waarop deze pagina is gebaseerd.

XAdES-uitleg van vijf minuten De uitgebreide snelstart: een nieuw VCL-project, een PFX-bestand en een ondertekende XML-envelop.
Sleutelproviders Alle tien de plekken waar een privésleutel kan staan en wat elk nodig heeft.
Handtekeningprofielen De eenentwintig land- en sectorprofielen en wat elk vereist.
Handleiding PDF ondertekenen Een uitgebreidere uitleg van PAdES, inclusief zichtbare handtekeningen.
sgcSign Server De zelf gehoste ondertekeningsdaemon, voor als de sleutel niet mag reizen.
Download de proefversie Hetzelfde installatieprogramma als de productieversie, beperkt in tijd, plus een gratis Community Edition.

Verder lezen: de introductie van sgcSign en de codeondertekeningsserver. Elk product heeft zijn eigen snelstart, te vinden op de pagina Aan de slag.

Vragen over de sgcSign-snelstart

TsgcPAdESSigner, gedeclareerd in sgcSign_PAdES.pas, en een sleutelprovider. Voor het Windows-certificaatarchief is dat TsgcWindowsCertStoreProvider, uit sgcSign_KeyProvider_WinCertStore.pas. Voor een .pfx-bestand is het TsgcPFXKeyProvider, uit sgcSign_KeyProvider_PFX.pas. Beide staan op de palettabpagina SGC Sign. Wijs de provider toe aan de eigenschap KeyProvider van de ondertekenaar en roep daarna SignPDFFile(aInputFile, aOutputFile).
Omdat KeyProvider is getypeerd als de interface IsgcKeyProvider, niet als component. Een inline as-cast maakt een door de compiler gegenereerde tijdelijke interface die in het stackframe in leven blijft tot de routine terugkeert, en dat is nadat het providercomponent is vrijgegeven. Het vrijgeven daarvan raakt dan geheugen aan dat er niet meer is. De demo wijst de cast toe aan een benoemde lokale variabele en geeft daarna vrij in de volgorde: ondertekenaar, interface op nil, provider. Neem die volgorde over.
Er zijn geen edities. De sgcVer.inc van het product bevat helemaal geen SGC_EDT_*-define en geen enkel component of formaat wordt per niveau afgeschermd. Elke licentie bevat elke ondertekenaar, elke sleutelprovider en elk landprofiel. De commerciële niveaus zijn aantallen gebruikers: Single, Team en Site, en naast de proefversie is er een gratis Community Edition.
Ja, sinds 2026.10.0. De bibliotheek bouwt en draait op Linux64, op macOS voor Intel en Apple Silicon, op iOS en op Android, evenals Win32 en Win64. Documenten ondertekenen en verifiëren, PKCS#12-bestanden lezen en schrijven, PE-bestanden, catalogi, MSI, MSP, MSIX en APPX ondertekenen en PKCS#11-tokens werken daar allemaal, en de ondertekeningsserver draait op Linux als systemd-daemon. Twee providers gebruiken de keystore die het platform al heeft: de Apple-sleutelhanger en de Android KeyStore. Twee dingen blijven op Windows: de provider voor het Windows-certificaatarchief en de Windows-specifieke formaten op de server en de opdrachtregeltool, die ze in een niet-Windows-build nog steeds weigeren, hoewel de bibliotheek zelf ze wel ondertekent.
Niet voor een eerste handtekening. De constructor stelt al een basis-PAdES-profiel, het baseline B-handtekeningniveau en SHA-256 in. Als je het wel wilt wijzigen, is Profile een TsgcSignProfileConfig-object, dus je stelt Profile.Profile en Profile.SignatureLevel in in plaats van een string toe te wijzen. Stap voor een langetermijnhandtekening over op het LTV-profiel en het baseline LT-niveau en koppel een TSAClient.
Gebruik TsgcSignatureVerifier. VerifyPDF neemt een stream en geeft een TsgcVerificationStatus terug, die je vergelijkt met vsValid. GetVerificationDetails verklaart een fout en GetValidationReportXML maakt een rapport in het ETSI-validatierapportformaat wanneer je bewijs nodig hebt in plaats van een boolean.
Nee. Op Windows hasht en ondertekent sgcSign via de CNG- en BCrypt-API's en communiceert het met het netwerk via WinHTTP. Op Linux, macOS, iOS en Android gebruikt het de eigen pure Pascal-cryptografie en de Delphi RTL HTTP-client. In beide gevallen zijn er geen OpenSSL-DLL's om mee te leveren, en dat is een van de redenen dat uitrollen eenvoudig is.
Ze behandelen bewust verschillende taken. De snelstart van vijf minuten bouwt een nieuw VCL-project, gebruikt een PFX-bestand en ondertekent een XML-document met XAdES, en gaat in op de Unicode-valkuil van Delphi 7 en de UTC-ondertekeningstijd. Deze pagina ondertekent een PDF met PAdES met een certificaat uit het Windows-archief, wat de meegeleverde PAdES-demo doet. Lees eerst deze en daarna die andere wanneer je XML nodig hebt.
De beste deal: All-AccessElk eSeGeCe-product, inclusief Premium-ondersteuning, vanaf €1,059 per jaar.
Bekijk de All-Access-prijzen

Klaar om je eerste document te ondertekenen?

Download de proefversie, of begin met de gratis Community Edition.