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

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

บทความนี้แสดงวิธีใช้ GroupDocs.Signature for .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, รวม timestamp, และฝังข้อมูลการตรวจสอบความถูกต้อง.
  3. ความแปรต่างของผู้ขาย – โทเค็นหรือโมดูลของผู้ขายต่างกันอาจต้องการการแมปแอตทริบิวต์แบบกำหนดเองหรือมี middleware เสริม.
  4. การปฏิบัติตามและการตรวจสอบ – ระบบการผลิตต้องการการจัดการ PIN ที่แข็งแรง, ควบคุมวงจรชีวิตของเซสชัน, การกู้คืนข้อผิดพลาด, และการบันทึก日志.

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

สิ่งที่โครงการตัวอย่างทำ

  • แสดง การเซ็นเอกสาร PDF ด้วยโทเค็น PKCS#11 (ดองเกิล, สมาร์ตการ์ด, HSM).
  • รองรับการสำรอง Windows certificate store: หากมีใบรับรองติดตั้งบน Windows โค้ดจะใช้ใบรับรองนั้นแทน.
  • ดำเนินการ custom hash signing: GroupDocs คำนวณดิจิสต์; โทเค็นเซ็นแฮชเท่านั้น.
  • เก็บกุญแจส่วนตัว บนฮาร์ดแวร์ ตลอดเวลา — ไม่เคยส่งออก.
  • รวมตรรกะของโทเค็น (เซสชัน, การค้นหากุญแจ, การเซ็น) ไว้ใน Pkcs11DigitalSigner.cs
  • ให้ตรรกะช่วยเหลือใน Helpers.cs (เช่น การค้นหาใบรับรองใน Windows store).
  • การตั้งค่าถูกศูนย์กลางใน Settings.cs.
  • ทำหน้าที่เป็นตัวอย่างอ้างอิงที่คุณสามารถปรับใช้กับสภาพแวดล้อมของคุณได้.
สะพานระหว่าง PKCS#11 กับการเซ็น PDF

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

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

  • .NET 6.0 หรือสูงกว่า (หรือ .NET Framework 4.6.2)
  • ไลบรารี PKCS#11 ที่ถูกต้อง (DLL) จากผู้ขายโทเค็นของคุณ
  • โทเค็นฮาร์ดแวร์ (ดองเกิล USB, สมาร์ตการ์ด, หรือ HSM) พร้อมใบรับรองที่ถูกต้อง
  • GroupDocs.Signature for .NET (รุ่นทดลองหรือที่มีล licença)
  • ไลบรารี 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 ตามชื่อ subject (ใช้สำหรับโฟลว์สำรอง).
  • 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 — High-Level Flow

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 — Usage Flow

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 ลายเซ็นที่ออกโดยหน่วยงานรับรอง
    ในอินเดียหลายระบบ eSignature ที่มีผลผูกพันกฎหมายต้องใช้ใบรับรองที่เก็บไว้ในดองเกิล USB ที่ออกโดยหน่วยงานที่ได้รับการรับรอง. ตัวอย่างนี้ช่วยให้แอป (เช่น ระบบประตูเอกสาร, พอร์ทัล) ติดต่อโดยตรงกับดองเกิลเหล่านี้.

  • กระบวนการทำงานเอกสารระดับองค์กร
    สำหรับระบบภายใน เช่น การจัดการสัญญาหรือขั้นตอนอนุมัติ, การเซ็นด้วยฮาร์ดแวร์ช่วยให้แน่ใจว่าผู้ที่ไม่ได้รับอนุญาตไม่สามารถปลอมแปลงลายเซ็นเอกสารได้.

  • การเซ็นเพื่อการปฏิบัติตามกฎหมาย/มาตรฐาน
    รัฐบาลและอุตสาหกรรมที่ได้รับการควบคุมมักกำหนดให้ลายเซ็นต้องมาจากคีย์ที่ควบคุมโดยฮาร์ดแวร์. การบูรณาการนี้ช่วยให้ตรงตามข้อกำหนดด้านการตรวจสอบและการปฏิบัติตามที่เข้มงวด.

ปัญหาที่พบบ่อยและการแก้ไขข้อขัดข้อง

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

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

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

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

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

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

ลิงก์ภายนอก