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

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

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

⚠️ اطلاعیه پیاده‌سازی اولیه
این راه‌حل در حال حاضر به عنوان یک پیاده‌سازی اولیه برای استفاده از دانگل‌های امضای دیجیتال PKCS#11 با GroupDocs.Signature ارائه شده است.
اگرچه امکان امضای اسناد با توکن‌های سخت‌افزاری را فراهم می‌کند، به شدت توصیه می‌کنیم تست‌های اضافی در محیط خود انجام دهید تا اطمینان حاصل شود که نیازهای انطباق و امنیتی شما را برآورده می‌کند.
بازخورد، نتایج تست و پیشنهادات شما برای بهبود بسیار قدردانی می‌شود.

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

یکپارچه‌سازی توکن‌های PKCS#11 در جریان‌های کاری امضای اسناد چند چالش غیر ساده دارد:

  1. پیچیدگی سطح پایین – API PKCS#11 (Cryptoki) نیاز به مدیریت اسلات‌ها، نشست‌ها، هندل‌ها و ویژگی‌ها برای یافتن کلید خصوصی صحیح دارد.
  2. بسته‌بندی سطح PDF – امضای یک PDF بیش از امضای بایت‌هاست: کتابخانه باید digests صحیح را بر روی بازه‌های بایتی انتخاب‌شده محاسبه کند، امضاها را در کانتینرهای CMS/PKCS#7 بپیچد، زمان‌مهرها را اضافه کند و اطلاعات اعتبارسنجی را جاسازی کند.
  3. تفاوت‌های فروشنده – ماژول‌های توکن/فروشنده مختلف ممکن است نیاز به نگاشت ویژگی‌های سفارشی یا میانی‌افزار اضافی داشته باشند.
  4. انطباق و قابلیت حسابرسی – سیستم‌های تولیدی به مدیریت PIN قوی، کنترل چرخه‌حیات نشست، بازیابی خطا و لاگ‌گیری نیاز دارند.

این پروژه نمونه با ترکیب رابط ICustomSignHash در GroupDocs.Signature و Pkcs11Interop، امضای توکن را بر عهده می‌گیرد در حالی که GroupDocs ساختار PDF را مدیریت می‌کند.

آنچه پروژه نمونه انجام می‌دهد

  • نشان می‌دهد چگونه اسناد PDF با توکن‌های PKCS#11 (دانگل، کارت هوشمند، HSM) امضا شوند.
  • پشتیبانی از بازگشت به فروشگاه گواهی‌نامه ویندوز: اگر گواهی‌نامه‌ای در ویندوز نصب شده باشد، کد می‌تواند به جای توکن از آن استفاده کند.
  • پیاده‌سازی امضای هش سفارشی: GroupDocs digest را محاسبه می‌کند؛ توکن فقط هش را امضا می‌کند.
  • کلید خصوصی در سخت‌افزار باقی می‌ماند — هرگز صادر نمی‌شود.
  • منطق توکن (نشست، جستجوی کلید، امضا) در Pkcs11DigitalSigner.cs محصور شده است.
  • منطق کمکی در Helpers.cs (مثلاً جستجوی گواهی‌نامه در فروشگاه ویندوز) فراهم شده است.
  • تنظیمات در 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      # فایل پروژه
├── 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، باز کردن نشست‌ها، یافتن شیء کلید خصوصی، امضای یک digest و بازگرداندن یک X509Certificate2 یا پیاده‌سازی callback امضا.
  • 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 متد مرکزی است: digest محاسبه‌شده توسط 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 امضای هش واقعی را به توکن واگذار کند.
  • جریان بازگشتی (کامنت‌گذاری شده) نشان می‌دهد چگونه می‌توان در صورت عدم دسترسی به توکن، به گواهی‌نامه فروشگاه ویندوز سوئیچ کرد.

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

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

مشکلات رایج و عیب‌یابی

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

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

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

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

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

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

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