Signer un programme Windows a toujours signifié avoir besoin d'une machine Windows. signtool ne fonctionne que sous Windows, si bien qu'un pipeline de build qui compile sous Linux a quand même besoin d'un hôte Windows quelque part, juste pour apposer une signature sur le fichier à la fin.
Depuis sgcSign 2026.10, cet hôte est optionnel. Le format Authenticode dans sgcSign, qui hache le fichier PE et construit la signature, est désormais du code Delphi plutôt qu'un appel aux API de signature de Windows. Sous Windows, l'opération de clé passe toujours par CNG, et partout ailleurs elle s'exécute dans la cryptographie propre à sgcSign, si bien que les composants qui signent un EXE sous Windows compilent et s'exécutent aussi sous Linux 64 bits, et Windows accepte le fichier qu'ils produisent comme n'importe quel autre fichier signé. Cet article montre un court programme console qui fait cela, comment le compiler pour Linux, et comment vérifier le résultat.
Le programme Delphi signant un EXE sous Ubuntu, puis le même fichier vérifié sous Windows. Également sur YouTube.
Pourquoi signer sous Linux
- Agents de build. Les runners CI hébergés et les conteneurs de build sont d'abord des environnements Linux. Signer sur le même agent qui a compilé le fichier supprime un saut vers une machine Windows et les identifiants que ce saut exige.
- Où vit la clé. Une clé de signature de code a sa place dans un HSM ou un coffre-fort de clés dans le cloud, et les deux sont accessibles depuis Linux tout aussi facilement. Les fournisseurs de clé PKCS#11 et cloud de sgcSign fonctionnent sur toutes les plateformes.
- Un seul outil partout. Le même programme Delphi signe sur le poste Windows d'un développeur et sur le serveur de publication, avec les mêmes options et la même sortie.
Le programme
Un programme console qui prend le fichier à signer, le fichier de sortie, un PFX avec son mot de passe et, en option, une autorité d'horodatage. C'est le même code sous Windows et sous Linux.
program SignExe;
{$APPTYPE CONSOLE}
uses
SysUtils, sgcSign_Authenticode, sgcSign_KeyProvider_PFX, sgcSign_TSA;
var
PFX: TsgcPFXKeyProvider;
TSA: TsgcTSAClient;
Signer: TsgcAuthenticodeSigner;
begin
if ParamCount < 4 then
begin
Writeln('usage: SignExe <input.exe> <output.exe> <file.pfx> <password> [tsa-url]');
Halt(1);
end;
PFX := TsgcPFXKeyProvider.Create(nil);
TSA := TsgcTSAClient.Create(nil);
Signer := TsgcAuthenticodeSigner.Create(nil);
try
try
PFX.LoadFromFile(ParamStr(3), ParamStr(4));
Signer.KeyProvider := PFX;
Signer.Hash := ahSHA256;
Signer.Level := alBES;
Signer.Description := 'sgcSign demo';
if ParamCount >= 5 then
begin
TSA.URL := ParamStr(5);
Signer.TSAClient := TSA;
Signer.Level := alT;
end;
Signer.SignFile(ParamStr(1), ParamStr(2));
Writeln('Signer: ', PFX.Certificate.Subject);
Writeln('Signed: ', ParamStr(2));
except
on E: Exception do
begin
Writeln('Error: ', E.Message);
ExitCode := 1;
end;
end;
finally
Signer.Free;
TSA.Free;
PFX.Free;
end;
end.
TsgcPFXKeyProvider détient le certificat et la clé privée. TsgcAuthenticodeSigner hache le fichier PE de la même façon que Windows, construit la signature PKCS#7 et l'écrit dans la table de certificats du fichier. Avec un TsgcTSAClient rattaché, il récupère aussi un horodatage RFC 3161, afin que la signature reste valide après l'expiration du certificat.
Le compiler pour Linux 64 bits
Dans la fenêtre Projects, ajoutez Linux 64-bit comme plateforme cible, avec un SDK Linux configuré dans le SDK Manager, puis compilez. Les paquets runtime de sgcSign sont compilés pour Linux64 à partir de Delphi 10.3. Sous Linux, le PFX est analysé en Pascal pur, puisqu'il n'existe pas de magasin de certificats Windows dans lequel l'importer, et l'opération RSA ou ECDSA s'exécute dans la cryptographie propre à sgcSign. Le format de signature qui l'entoure est construit par le même code que celui qui s'exécute sous Windows.
L'exécuter et vérifier le résultat
$ file Hello.exe
PE32+ executable (console) x86-64, for MS Windows
$ ./SignExe Hello.exe Hello-signed-linux.exe ../certs/demo.pfx demo http://timestamp.digicert.com
Signer: O=eSeGeCe Demo, CN=sgcSign Demo Code Signing
Signed: Hello-signed-linux.exe
Pour le vérifier sans Windows, osslsigncode verify recalcule l'empreinte du fichier et vérifie la signature qui s'y rapporte : Signature verification: ok.
Copiez ensuite le fichier vers Windows. PowerShell et signtool verify /pa /v lisent la même signature : l'empreinte du fichier calculée par Windows correspond à celle qui a été signée, le signataire est le certificat de démonstration, et l'horodatage DigiCert est vérifié. Le fichier s'exécute toujours.
PS> Get-AuthenticodeSignature .\Hello-signed-linux.exe | Format-List SignatureType,
@{n='Signer';e={$_.SignerCertificate.Subject}},
@{n='TimeStamper';e={$_.TimeStamperCertificate.Subject}}
SignatureType : Authenticode
Signer : CN=sgcSign Demo Code Signing, O=eSeGeCe Demo
TimeStamper : CN=DigiCert SHA256 RSA4096 Timestamp Responder 2026 1, O="DigiCert, Inc.", C=US
La seule réserve que fait Windows porte sur le certificat de démonstration, pas sur la signature. La chaîne de démonstration se termine par une racine de test autosignée qui n'est pas installée sur la machine, si bien que Windows ne peut pas la rattacher à une racine de confiance. L'empreinte, la signature et l'horodatage sont tous vérifiés.
Les mêmes octets sous Linux et sous Windows
Signez le même Hello.exe avec le même PFX et sans horodatage, une fois avec la version Linux et une fois avec la version Windows du programme ci-dessus, puis comparez les deux fichiers :
Linux 82344 bytes SHA-256 6FD63BB01A8E911AB099431BC76F3BFA4EF557082BFB8BC18CCBFA97A9E8079D
Windows 82344 bytes SHA-256 6FD63BB01A8E911AB099431BC76F3BFA4EF557082BFB8BC18CCBFA97A9E8079D
Ils sont identiques, octet pour octet. Une signature RSA de ce type est déterministe, et le signataire omet l'heure de signature sauf si on la demande, si bien que le fichier ne dépend que de la clé et de l'entrée, pas de la machine qui a signé. L'horodatage est le seul élément qui diffère d'une exécution à l'autre, car l'autorité d'horodatage marque le moment où on la sollicite.
D'où vient la clé
Sous Linux, la clé peut provenir d'un fichier PFX ou PEM, d'un jeton PKCS#11 ou d'un HSM, ou d'un service de signature dans le cloud : Azure Trusted Signing, AWS KMS, Google Cloud KMS, HashiCorp Vault ou un service de signature distante CSC. Le fournisseur du magasin de certificats Windows est celui qui reste exclusif à Windows, pour la raison évidente.
Pas seulement l'EXE
Cela vaut pour chaque composant de signature de code de sgcSign : TsgcAuthenticodeSigner pour EXE et DLL, TsgcCatalogSigner pour les catalogues .cat, TsgcMSISigner pour les fichiers .msi et .msp de Windows Installer, TsgcAppxSigner pour les paquets .msix et .appx, TsgcPowerShellSigner pour les scripts PowerShell, et TsgcAuthenticodeVerifier pour vérifier chacun d'eux. Tous compilent et s'exécutent sous Linux, macOS, iOS et Android.
Sur le serveur et en ligne de commande
La même chose vaut au-delà de la bibliothèque. Un sgcSign Server compilé pour Linux signe et vérifie les requêtes Authenticode, PowerShell, catalogue, MSI et MSIX exactement comme sous Windows, et l'outil en ligne de commande sgcsign les envoie depuis n'importe quelle plateforme. Une voie reste réservée à Windows dans l'outil en ligne de commande Delphi : calculer l'empreinte d'un EXE ou d'une DLL localement et n'envoyer que l'empreinte. L'outil en ligne de commande .NET emprunte cette voie sur toutes les plateformes.
Disponibilité
La signature de code sous Linux, macOS, iOS et Android arrive dans sgcSign 2026.10 pour Delphi. Rien ne change pour un programme Windows : les mêmes composants, les mêmes propriétés et la même sortie. Chaque propriété est documentée dans l'aide en ligne de sgcSign.
Des questions, ou un pipeline que vous voulez faire sortir de Windows ? Contactez-nous, et vous recevrez une réponse des personnes qui ont écrit le code.
