Wprowadzenie i Motywacja
Podczas implementacji podpisów cyfrowych w systemach klasy enterprise, bezpieczeństwo jest nie do negocjacji.
Przechowywanie certyfikatu w lokalnym pliku PFX lub P12 jest wygodne, ale naraża klucz prywatny na wyodrębnienie lub naruszenie. Natomiast tokeny sprzętowe PKCS#11 (takie jak klucze USB, karty inteligentne i HSM) przechowują klucze wewnątrz odpornej na manipulacje granicy, zapewniając, że nigdy nie opuszczą urządzenia.
Ten wpis demonstruje, jak używać GroupDocs.Signature for .NET wraz z Pkcs11Interop do podpisywania dokumentów PDF przy użyciu tokenów sprzętowych. Podejście łączy wygodę i zgodność: GroupDocs zajmuje się całym pakowaniem na poziomie PDF (pola podpisu, obliczanie skrótu, osadzanie), podczas gdy token wykonuje faktyczny kryptograficzny podpis.
⚠️ Wczesne powiadomienie o implementacji
To rozwiązanie jest obecnie udostępniane jako wczesna implementacja użycia kluczy USB PKCS#11 z GroupDocs.Signature.
Choć umożliwia podpisywanie dokumentów tokenami sprzętowymi, zdecydowanie zalecamy przeprowadzenie dodatkowych testów w własnym środowisku, aby upewnić się, że spełnia ono wymagania zgodności i bezpieczeństwa.
Będziemy bardzo wdzięczni za wszelkie opinie, wyniki testów oraz sugestie dotyczące ulepszeń.
Wyzwanie: Łączenie PKCS#11 z podpisywaniem PDF
Integracja tokenów PKCS#11 w procesy podpisywania dokumentów niesie ze sobą kilka niebanalnych wyzwań:
- Złożoność niskiego poziomu – API PKCS#11 (Cryptoki) wymaga zarządzania slotami, sesjami, uchwytami i atrybutami, aby odnaleźć właściwy klucz prywatny.
- Pakowanie na poziomie PDF – Podpisanie PDF to nie tylko podpisywanie bajtów: biblioteka musi obliczyć poprawne skróty nad wybranymi zakresami bajtów, opakować podpisy w kontenery CMS/PKCS#7, dołączyć znaczniki czasu i osadzić informacje weryfikacyjne.
- Różnice producentów – Różne tokeny/module dostawców mogą wymagać niestandardowego mapowania atrybutów lub dodatkowego oprogramowania pośredniczącego.
- Zgodność i audytowalność – Systemy produkcyjne potrzebują solidnego zarządzania PIN-em, kontroli cyklu życia sesji, odzyskiwania po błędach i logowania.
Ten przykładowy projekt rozwiązuje te problemy, łącząc interfejs ICustomSignHash w GroupDocs.Signature z Pkcs11Interop, aby przenieść podpisywanie na token, pozostawiając GroupDocs obsługę struktury PDF.
Co robi przykładowy projekt
- Demonstruje podpisywanie dokumentów PDF przy użyciu tokenów PKCS#11 (klucz USB, karta inteligentna, HSM).
- Obsługuje zapasowy dostęp do magazynu certyfikatów Windows: jeśli certyfikat jest zainstalowany w systemie Windows, kod może go użyć zamiast tokena.
- Implementuje niestandardowe podpisywanie skrótu: GroupDocs oblicza skrót; token podpisuje jedynie skrót.
- Przechowuje klucz prywatny na sprzęcie przez cały czas — nigdy nie jest eksportowany.
- Zawiera logikę tokena (sesja, wyszukiwanie klucza, podpisywanie) w pliku
Pkcs11DigitalSigner.cs - Dostarcza pomocniczą logikę w
Helpers.cs(na przykład wyszukiwanie certyfikatu w magazynie Windows). - Konfiguracja scentralizowana w
Settings.cs. - Działa jako referencyjna implementacja, którą możesz dostosować do swojego środowiska.
Konfiguracja i wymagania wstępne
Prerequisites
- .NET 6.0 lub nowszy (lub .NET Framework 4.6.2)
- Ważna biblioteka PKCS#11 (DLL) od dostawcy tokena
- Token sprzętowy (klucz USB, karta inteligentna lub HSM) z ważnym certyfikatem
- GroupDocs.Signature for .NET (wersja próbna lub licencjonowana)
- Biblioteka Pkcs11Interop
Installation
git clone https://github.com/groupdocs-signature/esign-documents-with-pkcs11-using-groupdocs-signature-dotnet.git
cd esign-documents-with-pkcs11-using-groupdocs-signature-dotnet
dotnet restore
Otwórz rozwiązanie w Visual Studio lub preferowanym IDE, upewnij się, że zależności są rozwiązane.
Szczegółowa struktura repozytorium
GroupDocs.Signature-for-.NET-PKCS11-Sample/
├── GroupDocs.Signature-for-.NET-PKCS11-Sample.csproj # Plik projektu
├── Program.cs # Punkt wejścia i przepływ użycia
├── Settings.cs # Konfiguracja PKCS#11 / tokena
├── Helpers.cs # Funkcje pomocnicze (magazyn Windows, filtrowanie certyfikatów)
├── Pkcs11DigitalSigner.cs # Implementuje ICustomSignHash przy użyciu PKCS#11
└── README.md # Wyjaśnienie i instrukcje użycia
- Program.cs – koordynuje podpisywanie; demonstruje zarówno przepływ oparty na tokenie, jak i na certyfikacie Windows.
- Settings.cs – zawiera stałe/miejsca zastępcze dla
Pkcs11LibraryPath,TokenPiniCertificateSubject. - Helpers.cs – zawiera kod służący do znajdowania certyfikatów w magazynie Windows po nazwie podmiotu (używany w trybie awaryjnym).
- Pkcs11DigitalSigner.cs – logika podstawowa: ładowanie modułu PKCS#11, otwieranie sesji, lokalizowanie obiektu klucza prywatnego, podpisywanie skrótu oraz zwracanie
X509Certificate2lub implementacji wywołania zwrotnego podpisu. - README.md – zawiera przegląd, wyzwania i instrukcje użycia (które uzupełnia ten blog).
Wyjaśnienie kodu i omówienie
Settings.cs
public static class Settings
{
public const string Pkcs11LibraryPath = "<PKCS11_LIBRARY_PATH>";
public const string TokenPin = "<TOKEN_PIN>";
public const string CertificateSubject = "<CERT_SUBJECT>";
}
To oddziela szczegóły konfiguracji, aby można je było łatwo podmienić w środowisku wdrożeniowym.
Pkcs11DigitalSigner.cs — przepływ wysokiego poziomu
public class Pkcs11DigitalSigner : ICustomSignHash
{
public byte[] SignHash(byte[] hash)
{
// This method is invoked by GroupDocs.Signature when it needs the token to sign a hash
using (var pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath, AppType.SingleThreaded))
{
// Load module, open session, login with PIN, find key and perform signing
}
}
public X509Certificate2 GetCertificateFromPkcs11()
{
// Retrieves the public certificate from the token so the signing options can be configured
}
}
SignHashjest centralną metodą: otrzymuje skrót obliczony przez GroupDocs, a następnie przy użyciu API PKCS#11 podpisuje go.GetCertificateFromPkcs11pobiera certyfikat (z kluczem publicznym) przechowywany w tokenie, aby metadane podpisu były prawidłowe.
Program.cs — przepływ użycia
class Program
{
static void Main()
{
string inputFile = "sample.pdf";
string outputFile = "signed.pdf";
// (1) PKCS#11 signing
var tokenSigner = new Pkcs11DigitalSigner();
var cert = tokenSigner.GetCertificateFromPkcs11();
using (var signature = new Signature(inputFile))
{
var options = new DigitalSignOptions(cert)
{
Comments = "Signed with PKCS#11 token",
SignTime = DateTime.Now,
CustomSignHash = tokenSigner // link token-based signing
};
signature.Sign(outputFile, options);
}
// (2) Windows certificate store fallback (optional)
// var storeCert = Helpers.GetCertificateFromWindowsStore(Settings.CertificateSubject);
// using (var signature2 = new Signature(inputFile))
// {
// var options2 = new DigitalSignOptions(storeCert) { ... };
// signature2.Sign("signed_store.pdf", options2);
// }
}
}
Kluczowe punkty:
- Właściwość
CustomSignHashwDigitalSignOptionsjest ustawiona natokenSigner, co pozwala GroupDocs delegować rzeczywiste podpisywanie skrótu na token. - Przepływ awaryjny (zakomentowany) pokazuje, jak przełączyć się na certyfikat z magazynu Windows, gdy token sprzętowy jest niedostępny.
Przypadki użycia i scenariusze rzeczywiste
-
Indie i dongle z certyfikatami wydanymi przez CA
W Indiach wiele prawnie wiążących e-podpisów wymaga certyfikatów przechowywanych w kluczach USB wydanych przez certyfikowane organy. Ten przykład umożliwia aplikacjom (np. bramkom dokumentów, portalom) bezpośrednią integrację z takimi kluczami. -
Korporacyjne przepływy dokumentów
Dla wewnętrznych systemów, takich jak zarządzanie umowami czy procesy zatwierdzania, podpisywanie sprzętowe zapewnia, że nieuprawnieni użytkownicy nie mogą fałszować podpisów dokumentów. -
Podpisy prawne / zgodne z wymogami
Rządy i regulowane branże często wymagają, aby podpisy pochodziły z kluczy kontrolowanych sprzętowo. Ta integracja pomaga spełnić surowe wymogi audytu i zgodności.
Typowe pułapki i rozwiązywanie problemów
- Niepoprawna ścieżka do biblioteki → Ścieżka do DLL PKCS#11 musi odpowiadać modułowi dostawcy tokena (np.
softhsm2.dll,cryptoki.dll). - Blokada lub niepowodzenie PIN → Wielokrotne błędne wprowadzenie PIN‑u może zablokować token; sprawdź politykę dostawcy.
- Klucz nie znaleziony → Upewnij się, że podano właściwy podmiot certyfikatu; token musi zawierać certyfikat z pasującym podmiotem.
- Brak sterownika lub oprogramowania pośredniczącego → Niektóre tokeny wymagają zainstalowanych sterowników dostawcy, zanim Pkcs11Interop będzie mógł się z nimi komunikować.
- Problemy z wątkowością → Operacje PKCS#11 mogą nie być wątkowo bezpieczne; używaj kontekstu jednowątkowego, chyba że dostawca obsługuje wielowątkowość.
- Timeouty lub resetowanie sesji → Długie operacje mogą powodować zamknięcie lub wygaśnięcie sesji; zapewnij prawidłowe zarządzanie sesjami i ich czyszczenie.
Bezpieczeństwo i najlepsze praktyki
- Nigdy nie wpisuj na stałe w kodzie produkcyjnych tajemnic (PIN‑y, ścieżki do bibliotek); używaj bezpiecznej konfiguracji lub zarządzania sekretami.
- Używaj silnych PIN‑ów i zmieniaj je zgodnie z polityką.
- Loguj operacje i błędy (bez logowania wrażliwych PIN‑ów).
- Ogranicz sesje tokena i wyloguj się natychmiast po podpisaniu.
- Waliduj podpis po jego utworzeniu (sprawdzanie łańcucha, znacznik czasu).
- Testuj w różnych środowiskach i typach tokenów (klucz USB/karta inteligentna/HSM).
Kolejne kroki i zasoby
Gotowy, aby wypróbować sam? Sklonuj repozytorium, zaktualizuj miejsca zastępcze i uruchom przykład. Tematy, które możesz chcieć zgłębić dalej:
- Niestandardowe podpisywanie skrótu (delegowanie skrótu + podpisywania do tokena)
- Znacznikowanie czasu i osadzanie LTV / DSS
- Iteracyjne podpisywanie (wiele podpisów w jednym dokumencie)
- Integracja z zdalnymi usługami HSM lub chmurowymi magazynami tokenów