İmzasız bir yükleyici, bir müşterinin ilk fark ettiği yanlış giden şeydir. SmartScreen bilinmeyen bir yayımcı hakkında uyarır, UAC istemi hiçbir ad göstermez, ve bir MSIX paketi hiç kurulmaz, çünkü Windows yalnızca geçerli bir imza taşıyan bir paketi kurar.
sgcSign 2026.10 bunun için iki bileşen ekler. TsgcMSISigner, Windows Installer .msi ve .msp dosyalarını imzalar, ve TsgcAppxSigner, .msix ve .appx paketlerini ve bunların paket demetlerini imzalar. Her ikisi de bir EXE için zaten kullanıyor olabileceğiniz Authenticode imzalayıcısıyla tamamen aynı şekilde çalışır: bir anahtar sağlayıcı, isteğe bağlı bir zaman damgası yetkilisi, tek bir çağrı.
Delphi programından imzalanan bir MSI ve bir MSIX, ve zaten hiçbir zaman kurulamayacak bir paketi durduran yayımcı denetimi. YouTube'da da izleyin.
Program
Dosya uzantısına göre imzalayıcıyı seçen, SHA-256 ile imzalayan ve bir zaman damgası yetkilisi verildiğinde RFC 3161 zaman damgası ekleyen tek bir konsol programı.
program SignInstaller;
{$APPTYPE CONSOLE}
uses
SysUtils, StrUtils, sgcSign_Authenticode, sgcSign_MSI, sgcSign_APPX,
sgcSign_KeyProvider_PFX, sgcSign_TSA;
var
PFX: TsgcPFXKeyProvider;
TSA: TsgcTSAClient;
Signer: TsgcAuthenticodeSigner;
begin
if ParamCount < 4 then
begin
WriteLn('usage: SignInstaller <input.msi|input.msix> <output> ' +
'<file.pfx> <password> [tsa-url]');
Halt(1);
end;
if MatchText(ExtractFileExt(ParamStr(1)), ['.msi', '.msp']) then
Signer := TsgcMSISigner.Create(nil)
else
Signer := TsgcAppxSigner.Create(nil); // .msix .appx and bundles
PFX := TsgcPFXKeyProvider.Create(nil);
TSA := TsgcTSAClient.Create(nil);
try
try
PFX.LoadFromFile(ParamStr(3), ParamStr(4));
Signer.KeyProvider := PFX;
Signer.Hash := ahSHA256;
Signer.Level := alBES;
if ParamCount > 4 then
begin
TSA.URL := ParamStr(5);
Signer.TSAClient := TSA;
Signer.Level := alT;
end;
if Signer is TsgcAppxSigner then
begin
WriteLn('Publisher : ', sgcAppxReadPublisher(ParamStr(1)));
WriteLn('Certificate: ', PFX.Certificate.SubjectRFC2253);
TsgcAppxSigner(Signer).SignFile(ParamStr(1), ParamStr(2));
end
else
TsgcMSISigner(Signer).SignFile(ParamStr(1), ParamStr(2));
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.
Her iki imzalayıcı da TsgcAuthenticodeSigner sınıfından türetilir, bu yüzden anahtar sağlayıcı, özet, zaman damgası düzeyi ve açıklama, tıpkı bir EXE için olduğu gibi ortak temel sınıf üzerinde ayarlanır ve SignFile hem temel tip üzerinden hem de somut sınıf üzerinde çağrılabilir.
Bir Windows Installer Paketini İmzalamak
Bir .msi dosyası bir PE dosyası değildir. Akışlardan ve depolardan oluşan küçük bir dosya sisteminden, yani bileşik bir dosyadan oluşur, ve Windows'un denetlediği özet, imza akışları hariç tutularak bu akışlar üzerinden belirli bir sırayla hesaplanır. TsgcMSISigner bu özeti hesaplar, PKCS#7 imzasını oluşturur ve paketin DigitalSignature akışına yazar. SHA-1, SHA-256, SHA-384 ve SHA-512 hepsi kabul edilir, ve bir RFC 3161 zaman damgası, sertifika süresi dolduktan sonra da imzayı geçerli tutar.
Yama paketleri (.msp) de aynı şekilde imzalanır. AppendSignature ayarlandığında, zaten imzalanmış bir paket, signtool /as'ın bir EXE'ye ikinci bir imza eklemesi gibi, ilkinin yanına ikinci bir imza alır.
Bir MSIX veya APPX Paketini İmzalamak
MSIX, blok haritası bulunan bir ZIP dosyasıdır ve Windows'un imzaladığı şey dosyanın bir özeti değil, parçaları üzerindeki özetlerden oluşan küçük bir yapıdır. TsgcAppxSigner bu yapıyı oluşturur, imzalar ve sonucu pakete AppxSignature.p7x olarak yazar. Paket henüz imza bölümünü bildirmiyorsa, bu bölüm eklenir. Windows bir paket için yalnızca SHA-256'yı kabul eder, bu yüzden sunulan tek özet budur, ve zaten imzalanmış bir paketi tekrar imzalamak eski imzanın yerini alır.
Yayımcı Denetimi
Bu, bir öğleden sonranıza mal olan hatadır. Paket bildiriminde (manifest) yer alan Publisher değeri, imzalama sertifikasının konusuyla (subject) tam olarak aynı olmalıdır. İkisi farklı olduğunda Windows hatalı bir imza bildirmez. Paketi tanımayı bırakır ve onu doğrulayamadığı bir dosya biçimi olarak adlandırır, bu da bozuk bir yapı (build) gibi görünür.
TsgcAppxSigner imzalamadan önce bunu denetler ve her iki değeri de belirten bir mesajla durur.
> SignInstaller.exe DemoApp-wrongpublisher.msix out.msix ..\certs\demo.pfx demo
Publisher : CN=Someone Else
Certificate: CN=sgcSign Demo Code Signing,O=eSeGeCe Demo
Error: APPX: the signing certificate subject "O=eSeGeCe Demo, CN=sgcSign Demo Code Signing"
does not match the Publisher declared in AppxManifest.xml ("CN=Someone Else"). Windows
requires them to be identical and refuses a package where they differ; signtool rejects
the same combination with 0x8007000B. Sign with a certificate whose subject matches the
manifest, or rebuild the package with the Publisher set to the certificate subject.
Karşılaştırma, bir dize olarak değil, öznitelik türü ve değeri üzerinden yapılır, bu yüzden bildirim ile sertifika arasındaki boşluk ve sıralama farkları yanlış alarma yol açmaz. ValidatePublisher (varsayılan olarak True) bu denetimi kapatır, ve sgcAppxReadPublisher ile sgcAppxDNMatches, örneğin bir yapıyı imzalama adımına ulaşmadan önce başarısız kılmak gibi, aynı karşılaştırmayı kendiniz çalıştırmanıza olanak tanır.
Sonucu Denetlemek
> SignInstaller.exe DemoApp.msi DemoApp-signed.msi ..\certs\demo.pfx demo http://timestamp.digicert.com
Signed: DemoApp-signed.msi
> SignInstaller.exe DemoApp.msix DemoApp-signed.msix ..\certs\demo.pfx demo http://timestamp.digicert.com
Publisher : CN=sgcSign Demo Code Signing, O=eSeGeCe Demo
Certificate: CN=sgcSign Demo Code Signing,O=eSeGeCe Demo
Signed: DemoApp-signed.msix
> Get-AuthenticodeSignature DemoApp-signed.msi, DemoApp-signed.msix |
Format-List Path, @{n='Signer';e={$_.SignerCertificate.Subject}},
@{n='TSA';e={$_.TimeStamperCertificate.Subject}}
Path : DemoApp-signed.msi
Signer : CN=sgcSign Demo Code Signing, O=eSeGeCe Demo
TSA : CN=DigiCert SHA256 RSA4096 Timestamp Responder 2026 1, O="DigiCert, Inc.", C=US
Path : DemoApp-signed.msix
Signer : CN=sgcSign Demo Code Signing, O=eSeGeCe Demo
TSA : CN=DigiCert SHA256 RSA4096 Timestamp Responder 2026 1, O="DigiCert, Inc.", C=US
Windows'ta signtool verify /pa /v, her iki dosyada da aynı imzalayıcıyı ve DigiCert zaman damgasını bulur, ve hesapladığı özet imzalanmış olan özettir. Tek şikayeti 0x800B010A'dır, çünkü demo zinciri makineye kurulu olmayan kendinden imzalı bir test kökünde sona erer. Bozuk bir özet veya imza bunun yerine 0x80096010 olurdu. TsgcAuthenticodeVerifier bir yükleyici paketini ve bir MSIX paketini kendi başına tanır, bu yüzden bir EXE'yi doğrulayan aynı çağrı bunları da doğrular.
Sunucuda ve Komut Satırında
sgcSign Server, /api/v1/sign/msi ve /api/v1/sign/appx adreslerinde her iki biçimi de imzalar, ve komut satırı aracı --format msi ile --format appx alır. Her ikisinin de yalnızca özet kullanan bir rotası vardır, bu yüzden büyük bir yükleyici asla ağdan geçmez; bu da bu serinin bir sonraki yazısının konusudur.
Kullanılabilirlik
TsgcMSISigner ve TsgcAppxSigner, sunucu rotaları ve komut satırı biçimleriyle birlikte Delphi ve C++Builder için sgcSign 2026.10 içinde sunulur. Windows'un yanı sıra Linux, macOS, iOS ve Android üzerinde de derlenir ve çalışır. Her özellik sgcSign çevrimiçi yardımında belgelenmiştir.
İmzalanamayan veya kurulamayan bir paketle ilgili sorularınız mı var? Bizimle iletişime geçin, kodu yazan kişilerden bir yanıt alacaksınız.
