Вступ та Мотивація
При впровадженні цифрових підписів у корпоративних системах безпека є
негнучливою вимогою.
Зберігання сертифіката у локальному файлі PFX або P12 зручне, але
дає можливість витягнути або скомпрометувати приватний ключ. Навпаки,
апаратні токени PKCS#11 (наприклад USB‑дони, смарт‑карти та HSM)
утримують ключі всередині захищеної оболонки, гарантуючи, що вони
ніколи не залишають пристрій.
У цьому дописі показано, як використати GroupDocs.Signature for .NET разом із Pkcs11Interop для підпису PDF‑документів апаратними токенами. Підхід поєднує зручність і відповідність вимогам: GroupDocs обробляє всю упаковку на рівні PDF (поля підпису, обчислення дайджесту, вбудовування), а токен виконує фактичне криптографічне підписання.
⚠️ Повідомлення про ранню реалізацію
Це рішення наразі надається як рання реалізація для використання USB‑доників цифрового підпису PKCS#11 разом із GroupDocs.Signature.
Хоча воно дозволяє підписувати документи апаратними токенами, ми настійно рекомендуємо виконати додаткове тестування у вашому середовищі, щоб переконатися, що воно відповідає вашим вимогам щодо відповідності та безпеки.
Ми будемо дуже вдячні за ваші відгуки, результати тестів та пропозиції щодо покращень.
Виклик: Поєднання PKCS#11 з підписанням PDF
Інтеграція токенів PKCS#11 у процеси підписання документів має кілька незвичних викликів:
- Низькорівнева складність — API PKCS#11 (Cryptoki) вимагає керування слотами, сесіями, дескрипторами та атрибутами для знаходження правильного приватного ключа.
- Упаковка на рівні PDF — підпис PDF — це більше, ніж підписання байтів: бібліотека повинна обчислювати правильні дайджести над вибраними діапазонами байтів, обгортати підписи у контейнери CMS/PKCS#7, включати часові мітки та вбудовувати інформацію про валідацію.
- Варіації виробників — різні токени/модулі можуть вимагати спеціального мапінгу атрибутів або додаткового проміжного ПЗ.
- Відповідність та аудит — у виробничих системах потрібне надійне управління PIN‑кодом, контроль життєвого циклу сесії, відновлення після помилок та журналювання.
Цей зразковий проєкт вирішує ці питання, поєднуючи інтерфейс ICustomSignHash у GroupDocs.Signature з Pkcs11Interop для перенесення підписання на токен, залишаючи GroupDocs обробляти структуру PDF.
Що робить зразковий проєкт
- Демонструє підписання PDF‑документів за допомогою токенів PKCS#11 (доник, смарт‑карта, HSM).
- Підтримує резервний варіант Windows Certificate Store: якщо сертифікат встановлений у Windows, код може використати його.
- Реалізує кастомне підписання хешу: GroupDocs обчислює дайджест, токен лише підписує хеш.
- Тримає приватний ключ на апаратному засобі весь час — ніколи не експортується.
- Інкапсулює логіку токену (сесія, пошук ключа, підпис) у файлі
Pkcs11DigitalSigner.cs. - Надає допоміжну логіку у
Helpers.cs(наприклад, пошук сертифіката у Windows Store). - Конфігурація централізована у
Settings.cs. - Служить референтною реалізацією, яку можна адаптувати під ваше середовище.
Налаштування та вимоги
Вимоги
- .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‑сервісами або хмарними сховищами токенів