مقدمه و انگیزه

هنگامی که امضای دیجیتال را در سیستم‌های سطح سازمانی پیاده‌سازی می‌کنیم، امنیت مورد بحث نیست.
ذخیره گواهی در یک فایل محلی PFX یا P12 راحت است اما کلید خصوصی را در معرض استخراج یا به خطر افتادن قرار می‌دهد. در مقابل، توکن‌های سخت‌افزاری PKCS#11 (مانند دانگل‌های USB، کارت‌های هوشمند و HSM) کلیدها را داخل یک مرز ضد خرابکاری نگه می‌دارند و اطمینان می‌دهند که کلیدها هرگز از دستگاه خارج نمی‌شوند.

این پست چگونگی استفاده از GroupDocs.Signature برای .NET همراه با Pkcs11Interop را برای امضای اسناد PDF با توکن‌های سخت‌افزاری نشان می‌دهد. این رویکرد ترکیبی از راحتی و انطباق است: GroupDocs تمام بسته‌بندی‌های سطح PDF (فیلدهای امضا، محاسبه دیجست، تعبیه) را بر عهده می‌گیرد، در حالی که توکن عملیات رمزنگاری واقعی را انجام می‌دهد.

⚠️ اعلان پیاده‌سازی اولیه
این راه‌حل در حال حاضر به عنوان یک پیاده‌سازی اولیه برای استفاده از دانگل‌های امضای دیجیتال 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 را مدیریت کند.

اتصال PKCS#11 به امضای PDF

راه‌اندازی و پیش‌نیازها

پیش‌نیازها

  • .NET 6.0 یا بالاتر (یا .NET Framework 4.6.2)
  • یک کتابخانه PKCS#11 معتبر (DLL) از فروشنده توکن شما
  • یک توکن سخت‌افزاری (دانگل USB، کارت هوشمند یا HSM) دارای گواهی معتبر
  • GroupDocs.Signature برای .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      # فایل پروژه
├── Program.cs                                             # نقطه ورود و جریان استفاده
├── Settings.cs                                            # پیکربندی PKCS#11 / توکن
├── Helpers.cs                                             # توابع کمکی (فروشگاه ویندوز، فیلتر گواهی)
├── Pkcs11DigitalSigner.cs                                 # پیاده‌سازی ICustomSignHash با PKCS#11
└── README.md                                              # توضیحات و راهنمای استفاده
  • Program.cs – هماهنگی امضا؛ نشان می‌دهد که چگونه هر دو مسیر توکن‑محور و فروشگاه ویندوز را می‌توان استفاده کرد.
  • Settings.cs – شامل ثابت‌ها/مکان‌گیرهای Pkcs11LibraryPath، TokenPin و CertificateSubject.
  • Helpers.cs – کد یافتن گواهی‌ها در فروشگاه ویندوز بر اساس نام موضوع (برای جریان بازگشتی).
  • 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)
    {
        // این متد توسط GroupDocs.Signature فراخوانی می‌شود زمانی که نیاز به امضای
        // یک دیجست دارد
        using (var pkcs11 = new Pkcs11(Settings.Pkcs11LibraryPath, AppType.SingleThreaded))
        {
            // بارگذاری ماژول، باز کردن جلسه، ورود با PIN، یافتن کلید و انجام امضا
        }
    }

    public X509Certificate2 GetCertificateFromPkcs11()
    {
        // دریافت گواهی عمومی از توکن برای تنظیم متادیتاهای امضا
    }
}
  • SignHash روش مرکزی است: دیجست محاسبه‌شده توسط GroupDocs را می‌گیرد و با APIهای PKCS#11 آن را امضا می‌کند.
  • GetCertificateFromPkcs11 گواهی (با کلید عمومی) ذخیره‌شده در توکن را برمی‌گرداند تا متادیتای امضا صحیح باشد.

Program.cs — جریان استفاده

class Program
{
    static void Main()
    {
        string inputFile = "sample.pdf";
        string outputFile = "signed.pdf";

        // (1) امضای PKCS#11
        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  // اتصال امضای مبتنی بر توکن
            };
            signature.Sign(outputFile, options);
        }

        // (2) بازگشت به فروشگاه گواهی ویندوز (اختیاری)
        // 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 عملیات واقعی امضای دیجست را به توکن واگذار کند.
  • جریان بازگشتی (کامنت‌گذاری‌شده) نشان می‌دهد که در صورت عدم دسترس بودن توکن، می‌توان به گواهی‌نامه فروشگاه ویندوز سوکت شد.

موارد استفاده و سناریوهای دنیای واقعی

  • دانگل‌های USB امضای الکترونیکی صادر شده توسط مراجع قانونی در هند
    در هند بسیاری از امضای‌های قانونی نیاز به گواهی‌های ذخیره‌شده در دانگل‌های USB صادرشده توسط مراجع معتبر دارند. این نمونه امکان یکپارچه‌سازی مستقیم برنامه‌ها (مانند دروازه‌های اسناد یا پورتال‌ها) با چنین دانگل‌هایی را فراهم می‌کند.
  • گردش‌کارهای اسناد سازمانی
    برای سیستم‌های داخلی مانند مدیریت قرارداد یا جریان‌های تایید، امضای سخت‌افزاری تضمین می‌کند که کاربران غیرمجاز نتوانند امضای اسناد را جعل کنند.
  • امضای قانونی/انطباقی
    دولت‌ها و صنایع تحت نظر اغلب ایجاب می‌کنند که امضاها از کلیدهای کنترل‌شده توسط سخت‌افزار صادر شوند. این یکپارچه‌سازی به برآورده کردن الزامات دقیق حسابرسی و انطباق کمک می‌کند.

نکات رایج و عیب‌یابی

  • مسیر کتابخانه نادرست → مسیر DLL PKCS#11 باید دقیقاً با ماژول فروشنده شما (مثلاً softhsm2.dll یا cryptoki.dll) منطبق باشد.
  • قفل یا شکست PIN → وارد کردن مکرر PIN اشتباه ممکن است توکن را قفل کند؛ سیاست فروشنده را بررسی کنید.
  • کلید یافت نشد → اطمینان حاصل کنید که نام موضوع گواهی صحیح وارد شده است؛ توکن باید گواهی با همان موضوع را داشته باشد.
  • درایور یا میدلور گمشده → برخی توکن‌ها قبل از اینکه Pkcs11Interop بتواند ارتباط برقرار کند، نیاز به نصب درایورهای فروشنده دارند.
  • مشکلات Threading → عملیات PKCS#11 ممکن است thread‑safe نباشد؛ به‌جز در صورتی که فروشنده از حالت چندنخی پشتیبانی کند، از زمینه single‑threaded استفاده کنید.
  • تاخیر یا بازنشانی جلسه → عملیات طولانی ممکن است باعث بسته شدن یا منقضی شدن جلسات شود؛ اطمینان حاصل کنید که session به‑درستی مدیریت و تمیز می‌شود.

امنیت و بهترین شیوه‌ها

  • هرگز رازهای تولیدی (PINها، مسیرهای کتابخانه) را به‌صورت hard‑code قرار ندهید؛ از پیکربندی امن یا سیستم مدیریت رازها استفاده کنید.
  • از PINهای قوی استفاده کنید و در صورت امکان آن‌ها را دوره‌ای چرخش دهید.
  • عملیات و خطاها را لاگ کنید (بدون ثبت PINهای حساس).
  • تعداد جلسات توکن را محدود کنید و بلافاصله پس از امضا logout کنید.
  • پس از امضا، امضا را اعتبارسنجی کنید (بررسی زنجیره، زمان‌مهر).
  • در محیط‌ها و انواع توکن‌های مختلف (دانگل/کارت هوشمند/HSM) تست کنید.

گام‌های بعدی و منابع

آماده‌اید که خودتان امتحان کنید؟ مخزن را کلون کنید، مقادیر placeholder را به‌روز کنید و نمونه را اجرا کنید.
موضوعاتی که ممکن است بعداً بخواهید بررسی کنید:

  • امضای سفارشی دیجست (واگذاری محاسبه دیجست و امضا به توکن)
  • زمان‌مهر و جاسازی LTV / DSS
  • امضای تکراری (چند امضا در یک سند)
  • یکپارچه‌سازی با سرویس‌های HSM از راه دور یا فروشگاه‌های توکن ابری

پیوندهای خارجی