Podpisywanie kodu ma problem z zarządzaniem kluczami. Typowa konfiguracja kopiuje plik .pfx lub podłącza token USB do każdego agenta kompilacji, który musi podpisać wydanie. Klucz prywatny trafia na maszyny uruchamiające niezaufane skrypty kompilacji, nie ma żadnego zapisu tego, co zostało podpisane i przez kogo, a rotacja certyfikatu oznacza ingerencję w każdego agenta. sgcSign 2026.6 odpowiada na to nowym serwerem podpisującym: samodzielnie hostowanym demonem, który udostępnia podpisywanie przez REST API z TLS, dzięki czemu Twoje potoki i deweloperzy podpisują zdalnie, a klucz podpisujący pozostaje w dokładnie jednym miejscu.
Klucz nigdy nie opuszcza serwera. Co więcej, serwer może obsługiwać token sprzętowy lub chmurowy KMS, dzięki czemu klucz w ogóle nie istnieje jako plik. Każde żądanie jest uwierzytelniane kluczem API, ograniczane szybkością i zapisywane w dzienniku audytu odpornym na manipulacje. Ten wpis opisuje, co serwer może podpisać, jak go skonfigurować, pięciominutowy szybki start oraz dwa sposoby jego wywołania: zwykły curl oraz dołączony klient wiersza poleceń sgcsign.
Co podpisuje
Jeden serwer, jedno API, osiem formatów podpisu. Ten sam kształt punktu końcowego (POST /api/v1/sign/<format>) obejmuje zarówno pliki wykonywalne, jak i dokumenty:
- Authenticode — pliki PE systemu Windows:
.exe,.dll,.sys,.msi,.cab,.ocx. Opcjonalne podwójne podpisywanie SHA-1 + SHA-256 dla starszych wersji Windows. - PAdES — dokumenty PDF, z powodem, lokalizacją, kontaktem i nazwą podpisującego.
- XAdES — XML, otaczany, otaczający lub odłączony, z krajowymi profilami e-fakturowania, takimi jak eIDAS, FacturaE, FatturaPA, KSeF, Peppol, VeriFactu i TicketBAI.
- CAdES — odłączony PKCS#7 (
.p7s) dla dowolnego ładunku. - ClickOnce — manifesty aplikacji i wdrożenia.
- NuGet — podpisywanie pakietów
.nupkg. - VSIX — pakiety rozszerzeń Visual Studio.
- PowerShell — skrypty
.ps1/.psm1/.psd1(Authenticode SIP).
Każdy format akceptuje opcjonalny adres URL znacznika czasu RFC 3161, dzięki czemu podpisy pozostają ważne po wygaśnięciu certyfikatu podpisującego. Towarzyszący punkt końcowy POST /api/v1/verify sprawdza istniejący podpis i zwraca podmiot podpisujący, ważność oraz znacznik czasu.
Wymienni dostawcy kluczy
Dostawca to nazwany uchwyt do klucza podpisującego. Wywołujący wskazuje dostawcę w każdym żądaniu; nigdy nie widzi klucza. Możesz zarejestrować ich tylu, ilu potrzebujesz, a ten sam serwer może łączyć lokalny PFX dla narzędzi wewnętrznych z certyfikatem EV opartym na chmurze dla wydań publicznych. Obsługiwanych jest dziewięć typów dostawców:
- Magazyn certyfikatów Windows (
WinCertStore) — wybiera certyfikat na podstawie odcisku palca lub podmiotu, idealny dla certyfikatów EV zarejestrowanych na tokenie. - PFX i PEM — pliki certyfikatu i klucza na dysku.
- PKCS#11 / HSM (
PKCS11) — tokeny sprzętowe, takie jak YubiKey, lub sieciowy HSM. - AWS KMS, Azure Trusted Signing, Google Cloud KMS, HashiCorp Vault i Certum SimplySign — klucz prywatny znajduje się w usłudze chmurowej i nigdy nie dociera do serwera.
Sekrety pozostają poza plikiem konfiguracyjnym. Każdy parametr, którego nazwa kończy się na _env, jest odczytywany ze zmiennej środowiskowej, dzięki czemu hasło do PFX, kod PIN tokena lub sekret chmurowy są dostarczane przez środowisko usługi, a nie zapisywane na dysku.
Konfigurowanie serwera
Cały serwer jest sterowany jednym plikiem JSON, sgcSignServer.conf.json (udokumentowana próbka jest dołączona jako sgcSignServer.conf.sample.json). Najwyższy poziom struktury to kilka bloków:
{
"server": {
"listen": "0.0.0.0",
"port": 8443,
"tls": {
"enabled": true,
"cert_file": "certs/server.crt",
"key_file": "certs/server.key"
},
"max_upload_mb": 512,
"firewall": {
"enabled": true,
"whitelist": ["10.0.0.0/8"],
"brute_force": { "enabled": true, "max_attempts": 5, "ban_duration_sec": 900 },
"rate_limit": { "enabled": true, "max_connections_per_ip": 30, "time_window_sec": 60 }
}
},
"storage": { "sqlite_path": "data/sgcsignserver.db" },
"admin": {
"initial_user": "admin",
"initial_password_env": "SGCSIGN_ADMIN_INIT_PW",
"session_timeout_minutes": 60
},
"audit": { "retention_days": 365 },
"providers": [
{
"name": "pfx-build",
"type": "PFX",
"params": { "file": "certs/build.pfx", "password_env": "SGCSIGN_PFX_PW" }
},
{
"name": "ev-release",
"type": "AzureTS",
"params": {
"tenant_id": "00000000-0000-0000-0000-000000000000",
"client_id": "00000000-0000-0000-0000-000000000000",
"client_secret_env": "SGCSIGN_AZURE_TS_SECRET",
"account": "your-account",
"certificate_profile": "your-profile",
"endpoint": "https://eus.codesigning.azure.net/"
}
}
]
}
Bloki bezpośrednio odpowiadają funkcjom. server ustawia adres powiązania, port (domyślnie 8443), certyfikat TLS i wbudowaną zaporę (listy zezwoleń i odmów IP, blokadę przy atakach brute-force, ograniczanie szybkości połączeń, zabezpieczenia przed przechodzeniem ścieżek i ładunkiem). storage wskazuje na bazę danych SQLite przechowującą użytkowników, klucze API, dziennik audytu i kolejkę webhooków. admin definiuje pierwszego użytkownika i czas trwania sesji. audit ustawia okno przechowywania. providers to powyższa lista.
Początkowe hasło administratora nigdy nie jest przechowywane w pliku. Przy pierwszym uruchomieniu, gdy tabela użytkowników jest pusta, serwer odczytuje zmienną środowiskową wskazaną przez initial_password_env (domyślnie SGCSIGN_ADMIN_INIT_PW) i tworzy konto administratora. Przy każdym kolejnym uruchomieniu ta zmienna jest ignorowana, więc inicjuje tylko pierwsze logowanie.
Szybki start w pięć minut
Zainstaluj serwer (kreator instalacji rejestruje usługę Windows lub uruchom sgcSignServer.exe --install), a następnie:
1. Utwórz testowy certyfikat do podpisywania kodu i wyeksportuj go jako PFX. W przypadku rzeczywistego wdrożenia importujesz certyfikat wydany przez Twój urząd CA lub pomijasz ten krok i zamiast tego wskazujesz dostawcy Twój token lub chmurowy KMS.
$cert = New-SelfSignedCertificate -Type CodeSigningCert `
-Subject "CN=sgcSign Quickstart" -KeyAlgorithm RSA -KeyLength 3072 `
-CertStoreLocation Cert:\CurrentUser\My -NotAfter (Get-Date).AddYears(1)
$pw = ConvertTo-SecureString "QuickStartPFX!" -Force -AsPlainText
Export-PfxCertificate -Cert $cert -Password $pw `
-FilePath "C:\Program Files\sgcSign Server\certs\quickstart.pfx"
2. Ustaw sekrety jako zmienne środowiskowe maszyny, aby konto usługi mogło je odczytać:
setx /M SGCSIGN_ADMIN_INIT_PW "ChangeMeNow!"
setx /M SGCSIGN_PFX_PW "QuickStartPFX!"
3. Napisz minimalną konfigurację z jednym dostawcą PFX (TLS wyłączony tylko do testu na localhost):
{
"server": { "listen": "127.0.0.1", "port": 8443, "tls": { "enabled": false } },
"storage": { "sqlite_path": "data/sgcsignserver.db" },
"admin": { "initial_user": "admin", "initial_password_env": "SGCSIGN_ADMIN_INIT_PW" },
"audit": { "retention_days": 365 },
"providers": [
{ "name": "pfx-quickstart", "type": "PFX",
"params": { "file": "certs/quickstart.pfx", "password_env": "SGCSIGN_PFX_PW" } }
]
}
4. Uruchom usługę i potwierdź, że nasłuchuje:
sc start sgcSignServer
sc query sgcSignServer
Jeśli zatrzymuje się przy uruchomieniu, uruchom go na pierwszym planie za pomocą sgcSignServer.exe --console --config <path>, aby zobaczyć błąd na żywo (brakujący SGCSIGN_ADMIN_INIT_PW lub nieczytelny PFX to zwykłe przyczyny). Flaga --selftest-providers ładuje konfigurację, inicjalizuje każdego dostawcę i kończy działanie, dzięki czemu możesz sprawdzić klucze przed wdrożeniem produkcyjnym.
5. Zaloguj się i utwórz klucz API. Otwórz http://localhost:8443/admin, zaloguj się jako admin początkowym hasłem i utwórz klucz API. Klucz w postaci jawnej jest pokazywany tylko raz przy tworzeniu; skopiuj go natychmiast. Klucze mają prefiks sgcsk_.
6. Podpisz testowy plik wykonywalny za pomocą curl:
curl -X POST http://localhost:8443/api/v1/sign/authenticode ^
-H "X-API-Key: sgcsk_..." ^
-F file=@app.exe ^
-F provider=pfx-quickstart ^
-F hash=sha256 ^
--output app-signed.exe
To cała pętla: skonfiguruj dostawcę, wydaj klucz, podpisz. Stąd zamieniasz samodzielnie podpisany PFX na rzeczywisty certyfikat, włączasz TLS i blokujesz zaporę do swojej podsieci CI.
Podpisywanie przez REST
Każde żądanie podpisania to POST z plikiem i kilkoma polami formularza. Uwierzytelnianie to jeden nagłówek, albo X-API-Key: sgcsk_..., albo Authorization: Bearer sgcsk_.... Odpowiedzią jest podpisany artefakt jako application/octet-stream, z podmiotem podpisującym i czasem trwania podpisywania zwracanymi w nagłówkach X-Sgcsign-Signer-Subject i X-Sgcsign-Duration-Ms.
Podpisywanie pliku PDF, z widocznym powodem i lokalizacją podpisu:
curl -X POST https://sign.acme.local:8443/api/v1/sign/pades \
-H "X-API-Key: sgcsk_..." \
-F file=@invoice.pdf \
-F provider=qualified-eu \
-F tsa_url=http://timestamp.digicert.com \
-F reason=Approved \
-F location="Madrid, Spain" \
-F signer_name="Acme Billing" \
-o invoice-signed.pdf
Podpisywanie faktury XML z profilem eIDAS XAdES:
curl -X POST https://sign.acme.local:8443/api/v1/sign/xades \
-H "X-API-Key: sgcsk_..." \
-F file=@invoice.xml \
-F provider=qualified-eu \
-F profile=eidas \
-F xades_type=enveloped \
-o invoice-signed.xml
Weryfikacja podpisu zwraca JSON, a nie plik:
curl -X POST https://sign.acme.local:8443/api/v1/verify \
-H "X-API-Key: sgcsk_..." \
-F file=@app-signed.exe \
-F format=authenticode
{ "valid": true, "status": "valid",
"subject": "CN=Acme Inc., O=Acme, C=US",
"has_timestamp": true, "timestamp_time": "2026-06-15T13:01:17.000Z" }
Klient wiersza poleceń sgcsign
Serwer jest dostarczany z sgcsign, małym wieloformatowym CLI z czterema poleceniami: sign, verify, keys i health. Adres URL serwera, klucz API i dostawca mogą pochodzić z flag lub ze zmiennych środowiskowych SGCSIGN_SERVER, SGCSIGN_APIKEY i SGCSIGN_PROVIDER, co utrzymuje sekrety poza wierszem poleceń w CI:
set SGCSIGN_SERVER=https://sign.acme.local:8443
set SGCSIGN_APIKEY=sgcsk_...
sgcsign sign -f authenticode -p pfx-build -o app-signed.exe app.exe ^
--tsa http://timestamp.digicert.com --desc "Acme Installer"
sgcsign verify -f authenticode app-signed.exe
W przypadku Authenticode istnieje sztuczka oszczędzająca przepustowość. W trybie wstępnego haszowania (--prehash, domyślnie włączony) CLI oblicza skrót PE lokalnie i przesyła tylko skrót, kilkaset bajtów zamiast wielomegabajtowego pliku binarnego. Serwer podpisuje skrót i zwraca odłączony blob PKCS#7, który klient osadza w pliku. Na agencie CI z ograniczoną przepustowością podpisującym duży instalator zamienia to wielomegabajtowe przesyłanie w niewielkie.
Bezpieczeństwo i operacje
Serwer jest zbudowany do działania bez nadzoru przed rzeczywistym kluczem podpisującym, więc powierzchnia operacyjna ma takie samo znaczenie jak kryptografia:
- Konsola administracyjna pod adresem
/admin: pulpit, klucze API, dostawcy, użytkownicy, projekty i ślad audytu, wszystko w przeglądarce. - Klucze API z limitami szybkości i dziennymi przydziałami przypisanymi do klucza. Klucz, który osiąga swój limit, otrzymuje
429z nagłówkiemRetry-After. - Projekty wielodostępne, dzięki czemu klucz przypisany do jednego zespołu nie może używać dostawców innego zespołu.
- Przepływ zatwierdzania (opcjonalny): dwuetapowy przepływ, w którym żądanie podpisania jest wstrzymywane do momentu zatwierdzenia przez operatora, dla certyfikatów wydań o wysokiej wartości.
- Dziennik audytu odporny na manipulacje: każde podpisanie, weryfikacja, logowanie i zmiana konfiguracji są łączone w łańcuch za pomocą skrótu, dzięki czemu zapis nie może zostać zmieniony po fakcie.
- Metryki Prometheus pod adresem
/api/v1/metricsoraz sondy liveness/readiness pod/api/v1/health, gotowe dla Twojego stosu monitorującego. - Wychodzące webhooki, które wysyłają zdarzenie JSON metodą POST przy każdej operacji podpisywania, aby zintegrować podpisywanie ze Slackiem, systemem SIEM lub pulpitem wydań.
- Specyfikacja OpenAPI 3.1 pod adresem
/api/v1/openapi.jsonz interaktywnym Swagger UI pod/api/v1/docs. - TLS 1.2+ z opcjonalną obsługą wyzwań ACME / Let's Encrypt, plus wbudowana zapora do filtrowania IP i ochrony przed nadużyciami.
Dlaczego hostować samodzielnie
Celem serwera jest zredukowanie floty ryzykownych, posiadających klucze agentów kompilacji do jednego utwardzonego punktu końcowego. Klucz podpisujący znajduje się wyłącznie na serwerze lub w HSM albo chmurowym KMS, który serwer obsługuje, nigdy na maszynach uruchamiających Twoje skrypty kompilacji. Dostęp jest kontrolowany przez tokeny API przypisane do kluczy z przydziałami, ograniczone do projektów, a każdy podpis jest rejestrowany w dzienniku audytu, który kontrolujesz. Rotacja certyfikatu, unieważnienie klucza skompromitowanego agenta lub udowodnienie, kto co podpisał, stają się jednym miejscem do sprawdzenia zamiast wielu.
Dostępność
sgcSign Server jest częścią sgcSign 2026.6.0. Działa jako usługa Windows lub aplikacja konsolowa, jest konfigurowany pojedynczym plikiem JSON pokazanym powyżej i sterowany za pomocą curl, dołączonego CLI sgcsign lub dowolnego klienta HTTP poprzez jego opis OpenAPI.
Pytania, opinie lub pomoc w konfiguracji? Skontaktuj się. Otrzymasz odpowiedź od osób, które napisały kod.
