บทนำและแรงจูงใจ

เมื่อทำการใช้งานลายเซ็นดิจิทัลในระบบระดับองค์กร ความปลอดภัยเป็นสิ่งที่ไม่อาจประนีประนอมได้.
การเก็บใบรับรองในไฟล์ PFX หรือ P12 บนเครื่องเป็นวิธีที่สะดวกแต่ทำให้กุญแจส่วนตัวเสี่ยงต่อการถูกดึงออกหรือถูกทำลาย. ในทางตรงกันข้าม, PKCS#11 hardware tokens (เช่น USB dongles, smart cards, และ HSM) จะเก็บกุญแจไว้ภายในขอบเขตที่ทนต่อการดัดแปลง, ทำให้กุญแจไม่เคยออกจากอุปกรณ์.

บทความนี้จะแสดงวิธีการใช้ GroupDocs.Signature for .NET ร่วมกับ Pkcs11Interop เพื่อเซ็นเอกสาร PDF ด้วย hardware tokens. วิธีการนี้ผสานความสะดวกและการปฏิบัติตามมาตรฐาน: GroupDocs จะจัดการส่วนของ PDF ทั้งหมด (ฟิลด์ลายเซ็น, การคำนวณ digest, การฝังลายเซ็น) ส่วน token จะทำการเซ็นคริปโตกราฟิกจริง.

⚠️ หมายเหตุการนำไปใช้เบื้องต้น
โซลูชันนี้ในขณะนี้จัดให้เป็นการนำไปใช้เบื้องต้นสำหรับการใช้ dongles ลายเซ็นดิจิทัลแบบ PKCS#11 กับ GroupDocs.Signature.
แม้ว่าจะทำให้สามารถเซ็นเอกสารด้วย hardware tokens ได้, เราขอแนะนำให้ทำการทดสอบเพิ่มเติมในสภาพแวดล้อมของคุณเองเพื่อให้แน่ใจว่าเป็นไปตามข้อกำหนดด้านการปฏิบัติตามและความปลอดภัยของคุณ.
เราจะขอบคุณอย่างยิ่งหากคุณให้ข้อเสนอแนะ, ผลการทดสอบ, และข้อแนะนำเพื่อการปรับปรุง.

ความท้าทาย: การเชื่อมต่อ PKCS#11 กับการเซ็น PDF

การรวม token PKCS#11 เข้ากับกระบวนการเซ็นเอกสารมีความท้าทายหลายประการที่ไม่ใช่เรื่องง่าย:

  1. ความซับซ้อนระดับต่ำ – API ของ PKCS#11 (Cryptoki) ต้องการการจัดการ slot, session, handle, และ attribute เพื่อค้นหา private key ที่ถูกต้อง.
  2. การบรรจุระดับ PDF – การเซ็น PDF ไม่ได้เป็นแค่การเซ็นไบต์เท่านั้น: ไลบรารีต้องคำนวณ digest ที่ถูกต้องบนช่วงไบต์ที่เลือก, ห่อลายเซ็นในคอนเทนเนอร์ CMS/PKCS#7, รวม timestamp, และฝังข้อมูลการตรวจสอบ.
  3. ความแตกต่างของผู้ผลิต – Token หรือโมดูลของผู้ผลิตต่างกันอาจต้องการการแมป attribute เฉพาะหรือ middleware เพิ่มเติม.
  4. การปฏิบัติตามและการตรวจสอบ – ระบบการผลิตต้องการการจัดการ PIN ที่มั่นคง, การควบคุมวงจรชีวิตของ session, การกู้คืนข้อผิดพลาด, และการบันทึก.

ตัวอย่างโปรเจกต์นี้แก้ไขปัญหาเหล่านี้โดยการผสาน ICustomSignHash interface ของ GroupDocs.Signature กับ Pkcs11Interop เพื่อให้การเซ็นทำโดย token, ในขณะที่ให้ GroupDocs จัดการโครงสร้าง PDF.

สิ่งที่ตัวอย่างโปรเจกต์ทำ

  • แสดง การเซ็นเอกสาร PDF ด้วย token PKCS#11 (dongle, smart card, HSM).
  • รองรับการสำรองด้วย Windows certificate store: หากมีใบรับรองติดตั้งบน Windows, โค้ดสามารถใช้ได้แทน.
  • ดำเนินการ custom hash signing: GroupDocs คำนวณ digest; token ทำการเซ็น hash เท่านั้น.
  • เก็บ private key บนฮาร์ดแวร์ ตลอดเวลา — ไม่เคยถูกส่งออก.
  • แยกตรรกะของ token (session, การค้นหา key, การเซ็น) ไว้ใน Pkcs11DigitalSigner.cs
  • มี logic ช่วยเหลือใน Helpers.cs (เช่น การค้นหาใบรับรองใน Windows store).
  • การตั้งค่าถูกรวมไว้ใน Settings.cs.
  • ทำหน้าที่เป็น reference implementation ที่คุณสามารถปรับใช้กับสภาพแวดล้อมของคุณได้.
Bridging PKCS#11 with PDF Signing

การตั้งค่าและข้อกำหนดเบื้องต้น

ข้อกำหนดเบื้องต้น

  • .NET 6.0 หรือสูงกว่า (หรือ .NET Framework 4.6.2)
  • ไลบรารี PKCS#11 (DLL) ที่ถูกต้องจากผู้ผลิต token ของคุณ
  • hardware token (USB dongle, smart card, หรือ 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 ที่คุณชื่นชอบ, ตรวจสอบให้แน่ใจว่าขึ้นต่อ dependencies แล้ว.

โครงสร้างรีโพซิทอรีแบบลึก

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 — ประสานการเซ็น; แสดงการทำงานทั้งแบบใช้ token และแบบใช้ cert จาก Windows store.
  • Settings.cs — มีค่าคงที่/placeholder สำหรับ Pkcs11LibraryPath, TokenPin, และ CertificateSubject.
  • Helpers.cs — มีโค้ดสำหรับค้นหาใบรับรองใน Windows store ตามชื่อ subject (ใช้ใน flow สำรอง).
  • Pkcs11DigitalSigner.cs — โลจิกหลัก: โหลดโมดูล PKCS#11, เปิด session, ค้นหา private key object, เซ็น digest, และคืนค่า X509Certificate2 หรือ implementation ของ 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 ดึงใบรับรองสาธารณะจาก token เพื่อให้เมตาดาต้าลายเซ็นถูกต้อง.

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 มอบหมายการเซ็น hash ให้ token.
  • โฟลว์สำรอง (ที่คอมเมนต์) แสดงวิธีสลับไปใช้ cert จาก Windows store เมื่อ hardware token ไม่พร้อมใช้งาน.

กรณีการใช้งานและสถานการณ์จริง

  • India & CA‑Issued USB Signature Dongles
    ในอินเดียหลายกรณีของ eSignature ที่มีผลบังคับต้องใช้ใบรับรองที่เก็บใน USB dongles ที่ออกโดยหน่วยงานที่ได้รับการรับรอง. ตัวอย่างนี้ทำให้แอป (เช่น portal เอกสาร, gateway) สามารถเชื่อมต่อโดยตรงกับ dongles เหล่านั้น.
  • Enterprise Document Workflows
    สำหรับระบบภายในเช่นการจัดการสัญญาหรือกระบวนการอนุมัติ, การเซ็นด้วย hardware จะทำให้ผู้ใช้ที่ไม่ได้รับอนุญาตไม่สามารถปลอมแปลงลายเซ็นเอกสารได้.
  • Legal / Compliance‑Driven Signing
    รัฐบาลและอุตสาหกรรมที่อยู่ภายใต้การควบคุมมักกำหนดให้ลายเซ็นมาจากกุญแจที่ควบคุมโดยฮาร์ดแวร์. การผสานนี้ช่วยให้ตอบสนองต่อข้อกำหนดด้านการตรวจสอบและการปฏิบัติตามที่เข้มงวด.

ข้อผิดพลาดทั่วไปและการแก้ไขปัญหา

  • Incorrect library path → ต้องตรวจสอบให้แน่ใจว่าเส้นทาง DLL ของ PKCS#11 ตรงกับโมดูลของผู้ผลิต (เช่น softhsm2.dll, cryptoki.dll).
  • PIN lock or failure → การใส่ PIN ผิดหลายครั้งอาจทำให้ token ถูกล็อก; ตรวจสอบนโยบายของผู้ผลิต.
  • Key not found → ตรวจสอบให้แน่ใจว่าได้ระบุ CertificateSubject ที่ถูกต้อง; token ต้องมีใบรับรองที่ตรงกับ subject นั้น.
  • Driver or middleware missing → บาง token ต้องการให้ติดตั้งไดรเวอร์ของผู้ผลิตก่อนที่ Pkcs11Interop จะสื่อสารได้.
  • Threading issues → การทำงานของ PKCS#11 อาจไม่รองรับหลายเธรด; ใช้ context แบบ single‑threaded เว้นแต่ผู้ผลิตระบุว่ารองรับหลายเธรด.
  • Timeouts or session resets → การทำงานที่ใช้เวลานานอาจทำให้ session ปิดหรือหมดเวลา; ควรจัดการ session อย่างเหมาะสมและทำความสะอาดหลังใช้งาน.

ความปลอดภัยและแนวทางปฏิบัติที่ดีที่สุด

  • อย่า hard‑code ความลับในสภาพแวดล้อมการผลิต (PIN, เส้นทางไลบรารี); ใช้การตั้งค่าที่ปลอดภัยหรือระบบจัดการความลับ.
  • ใช้ PIN ที่แข็งแรง และหมุน PIN ตามนโยบายที่เป็นไปได้.
  • บันทึกการดำเนินการและข้อผิดพลาด (โดยไม่บันทึก PIN ที่เป็นความลับ).
  • จำกัดจำนวน session ของ token และทำการ logout ทันทีหลังเซ็น.
  • ตรวจสอบลายเซ็นหลังการเซ็น (ตรวจสอบ chain, timestamp).
  • ทดสอบในหลายสภาพแวดล้อมและกับประเภท token ต่าง ๆ (dongle/smart card/HSM).

ขั้นตอนต่อไปและแหล่งข้อมูล

พร้อมจะลองใช้งานแล้วหรือยัง? คัดลอก repo, ปรับค่า placeholder, แล้วรันตัวอย่าง.
หัวข้อที่คุณอาจอยากสำรวจต่อ:

  • Custom Hash Signing (มอบหมายการคำนวณ digest + การเซ็นให้ token)
  • Timestamping & LTV / DSS embedding
  • Iterative signing (หลายลายเซ็นในเอกสารเดียว)
  • Integration with remote HSM services or cloud‑based token stores

ลิงก์ภายนอก