Вступ та Мотивація

При впровадженні цифрових підписів у корпоративних системах безпека є негнучливою вимогою.
Зберігання сертифіката у локальному файлі PFX або P12 зручне, але дає можливість витягнути або скомпрометувати приватний ключ. Навпаки, апаратні токени PKCS#11 (наприклад USB‑дони, смарт‑карти та HSM) утримують ключі всередині захищеної оболонки, гарантуючи, що вони ніколи не залишають пристрій.

У цьому дописі показано, як використати GroupDocs.Signature for .NET разом із Pkcs11Interop для підпису PDF‑документів апаратними токенами. Підхід поєднує зручність і відповідність вимогам: GroupDocs обробляє всю упаковку на рівні PDF (поля підпису, обчислення дайджесту, вбудовування), а токен виконує фактичне криптографічне підписання.

⚠️ Повідомлення про ранню реалізацію
Це рішення наразі надається як рання реалізація для використання USB‑доників цифрового підпису PKCS#11 разом із GroupDocs.Signature.
Хоча воно дозволяє підписувати документи апаратними токенами, ми настійно рекомендуємо виконати додаткове тестування у вашому середовищі, щоб переконатися, що воно відповідає вашим вимогам щодо відповідності та безпеки.
Ми будемо дуже вдячні за ваші відгуки, результати тестів та пропозиції щодо покращень.

Виклик: Поєднання PKCS#11 з підписанням PDF

Інтеграція токенів PKCS#11 у процеси підписання документів має кілька незвичних викликів:

  1. Низькорівнева складність — API PKCS#11 (Cryptoki) вимагає керування слотами, сесіями, дескрипторами та атрибутами для знаходження правильного приватного ключа.
  2. Упаковка на рівні PDF — підпис PDF — це більше, ніж підписання байтів: бібліотека повинна обчислювати правильні дайджести над вибраними діапазонами байтів, обгортати підписи у контейнери CMS/PKCS#7, включати часові мітки та вбудовувати інформацію про валідацію.
  3. Варіації виробників — різні токени/модулі можуть вимагати спеціального мапінгу атрибутів або додаткового проміжного ПЗ.
  4. Відповідність та аудит — у виробничих системах потрібне надійне управління PIN‑кодом, контроль життєвого циклу сесії, відновлення після помилок та журналювання.

Цей зразковий проєкт вирішує ці питання, поєднуючи інтерфейс ICustomSignHash у GroupDocs.Signature з Pkcs11Interop для перенесення підписання на токен, залишаючи GroupDocs обробляти структуру PDF.

Що робить зразковий проєкт

  • Демонструє підписання PDF‑документів за допомогою токенів PKCS#11 (доник, смарт‑карта, HSM).
  • Підтримує резервний варіант Windows Certificate Store: якщо сертифікат встановлений у Windows, код може використати його.
  • Реалізує кастомне підписання хешу: GroupDocs обчислює дайджест, токен лише підписує хеш.
  • Тримає приватний ключ на апаратному засобі весь час — ніколи не експортується.
  • Інкапсулює логіку токену (сесія, пошук ключа, підпис) у файлі Pkcs11DigitalSigner.cs.
  • Надає допоміжну логіку у Helpers.cs (наприклад, пошук сертифіката у Windows Store).
  • Конфігурація централізована у Settings.cs.
  • Служить референтною реалізацією, яку можна адаптувати під ваше середовище.
Bridging PKCS#11 with PDF Signing

Налаштування та вимоги

Вимоги

  • .NET 6.0 або вище (або .NET Framework 4.6.2)
  • Дійсна бібліотека PKCS#11 (DLL) від вашого постачальника токену
  • Апаратний токен (USB‑доник, смарт‑карта або HSM) з дійсним сертифікатом
  • GroupDocs.Signature for .NET (триальна або ліцензована)
  • Бібліотека Pkcs11Interop

Встановлення

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

Відкрийте рішення у Visual Studio або вашому улюбленому IDE, переконайтеся, що всі залежності підключені.

Структура репозиторію – детальний огляд

GroupDocs.Signature-for-.NET-PKCS11-Sample/
├── GroupDocs.Signature-for-.NET-PKCS11-Sample.csproj      # Project file
├── Program.cs                                             # Entry point and usage flow
├── Settings.cs                                            # PKCS#11 / token configuration
├── Helpers.cs                                             # Utility functions (Windows store, certificate filtering)
├── Pkcs11DigitalSigner.cs                                 # Implements ICustomSignHash via PKCS#11
└── README.md                                              # Explanation & usage instructions
  • Program.cs — оркеструє підписання; демонструє як токен‑базовий, так і потік Windows‑сертифіката.
  • Settings.cs — містить константи/заповнювачі для Pkcs11LibraryPath, TokenPin та CertificateSubject.
  • Helpers.cs — код для пошуку сертифікатів у Windows Store за іменем суб’єкта (використовується у резервному потоці).
  • Pkcs11DigitalSigner.cs — ядро логіки: завантаження модуля PKCS#11, відкриття сесій, пошук об’єкта приватного ключа, підписання дайджесту та повернення X509Certificate2 або реалізації зворотного виклику підпису.
  • README.md — надає огляд, виклики та інструкції з використання (які доповнює цей блог).

Пояснення коду та покроковий огляд

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>";
}

Цей файл ізолює параметри конфігурації, щоб їх можна було легко змінити у вашому середовищі розгортання.

Pkcs11DigitalSigner.cs — загальний потік

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
    }
}
  • SignHash — центральний метод: отримує дайджест, обчислений GroupDocs, і за допомогою API PKCS#11 підписує його.
  • GetCertificateFromPkcs11 — отримує сертифікат (з відкритим ключем), що зберігається у токені, щоб метадані підпису були коректними.

Program.cs — потік використання

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);
        // }
    }
}

Ключові моменти:

  • Властивість CustomSignHash у DigitalSignOptions встановлюється в tokenSigner, що дозволяє GroupDocs делегувати фактичне підписання хешу токену.
  • Резервний потік (закоментовано) показує, як переключитися на сертифікат Windows Store, коли апаратний токен недоступний.

Випадки використання та реальні сценарії

  • Індія та USB‑доники, видані ЦА
    В Індії багато юридично обов’язкових e‑підписів вимагають сертифікатів, збережених у USB‑дониках, виданих акредитованими органами. Цей зразок дозволяє додаткам (наприклад, шлюзам документів, порталам) інтегруватися безпосередньо з такими доніками.
  • Корпоративні документообігові процеси
    Для внутрішніх систем, таких як управління контрактами чи процеси затвердження, апаратне підписання гарантує, що неавторизовані користувачі не зможуть підробити підписи.
  • Юридичне / регуляторне підписання
    Уряди та регульовані галузі часто вимагають, щоб підписи надходили з ключами, контрольованими апаратурою. Така інтеграція допомагає відповідати суворим вимогам аудиту та відповідності.

Поширені помилки та усунення проблем

  • Неправильний шлях до бібліотеки → Шлях до DLL PKCS#11 має точно відповідати модулю вашого постачальника (наприклад softhsm2.dll, cryptoki.dll).
  • Блокування або помилка PIN‑коду → Багато неправильних спроб може заблокувати токен; перевірте політику виробника.
  • Ключ не знайдено → Переконайтеся, що вказано правильний суб’єкт сертифіката; токен має містити сертифікат з відповідним суб’єктом.
  • Відсутність драйвера або проміжного ПЗ → Деякі токени вимагають встановлення драйверів виробника перед тим, як Pkcs11Interop зможе з ними спілкуватися.
  • Проблеми з потоковістю → Операції PKCS#11 можуть бути не потокобезпечними; використовуйте однопотоковий контекст, якщо виробник не підтримує багатопотоковість.
  • Тайм‑аути або скидання сесії → Довгі операції можуть призвести до закриття або тайм‑ауту сесії; забезпечте правильне управління сесіями та їх очищення.

Безпека та кращі практики

  • Ніколи не вшивайте у код секрети продакшн‑оточення (PIN‑коди, шляхи до бібліотек); використовуйте захищені конфігурації або менеджери секретів.
  • Використовуйте сильні PIN‑коди та змінюйте їх згідно політики.
  • Ведіть журнал операцій та помилок (не записуючи чутливі PIN‑коди).
  • Обмежуйте кількість сесій токену та виходьте з системи одразу після підписання.
  • Перевіряйте підпис після створення (перевірка ланцюжка, часових міток).
  • Тестуйте у різних середовищах та з різними типами токенів (доник/смарт‑карта/HSM).

Наступні кроки та ресурси

Готові спробувати? Клонуйте репозиторій, оновіть заповнювачі та запустіть зразок. Теми, які варто вивчити далі:

  • Кастомне підписання хешу (делегування обчислення дайджесту та підпису токену)
  • Тайм‑стемпінг та LTV / DSS вбудовування
  • Ітеративне підписання (декілька підписів в одному документі)
  • Інтеграція з віддаленими HSM‑сервісами або хмарними сховищами токенів

Зовнішні посилання