كيفية إضافة توقيع بطاقة ذكية إلى PDF

Aspose.PDF for .NET يقدم الوظيفة لإضافة توقيعات رقمية من موقع تخزين المفاتيح. يمكنك تطبيق التوقيع من خلال قبول الشهادة المقدمة من مخزن الشهادات، بطاقة ذكية أو بطاقة PIV متصلة بالنظام أثناء وقت التشغيل.

تعمل مقتطفات الشيفرة التالية أيضًا مع مكتبة Aspose.PDF.Drawing.

فيما يلي مقتطفات الشيفرة لتوقيع مستند PDF من بطاقة ذكية:

التوقيع باستخدام بطاقة ذكية باستخدام حقل التوقيع

// For complete examples and data files, visit https://github.com/aspose-pdf/Aspose.PDF-for-.NET
private static void GetSignatureInfo()
{
    // The path to the documents directory
    var dataDir = RunExamples.GetDataDir_AsposePdf_SecuritySignatures();

    // Open a document stream
    using (var fs = new FileStream(dataDir + "blank.pdf", FileMode.Open, FileAccess.ReadWrite))
    {
        // Open PDF document from stream
        using (var document = new Aspose.Pdf.Document(fs))
        {
            // Create a signature field
            var field1 = new Aspose.Pdf.Forms.SignatureField(document.Pages[1], new Aspose.Pdf.Rectangle(100, 400, 10, 10));

            // Sign with certificate selection in the windows certificate store
            var store = new X509Store(StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);
            
            // Manually chose the certificate in the store
            var sel = X509Certificate2UI.SelectFromCollection(store.Certificates, null, null, X509SelectionFlag.SingleSelection);

            // Set an external signature settings
            var externalSignature = new Aspose.Pdf.Forms.ExternalSignature(sel[0])
            {
                Authority = "Me",
                Reason = "Reason",
                ContactInfo = "Contact"
            };
            // Set a name of signature field
            field1.PartialName = "sig1";
            // Add the signature field to the document
            document.Form.Add(field1, 1);
            // Sign the document
            field1.Sign(externalSignature);
            // Save PDF document
            document.Save(dataDir + "externalSignature1_out.pdf");
        }
    }
}

private static void VerifyExternalSignature()
{    
    // The path to the documents directory
    var dataDir = RunExamples.GetDataDir_AsposePdf_SecuritySignatures();

    // Open PDF document
    using (var document = new Aspose.Pdf.Document(dataDir + "externalSignature1.pdf"))
    {
        using (var pdfSign = new Aspose.Pdf.Facades.PdfFileSignature(document))
        {
            var sigNames = pdfSign.GetSignatureNames();
            for (int index = 0; index <= sigNames.Count - 1; index++)
            {
                if (!pdfSign.VerifySignature(sigNames[index]))
                {
                    throw new Exception("Not verified");
                }
            }
        }
    }
}

التوقيع باستخدام بطاقة ذكية باستخدام توقيع ملف PDF

// For complete examples and data files, visit https://github.com/aspose-pdf/Aspose.PDF-for-.NET
private void SignWithSmartCard()
{
    // The path to the documents directory
    var dataDir = RunExamples.GetDataDir_AsposePdf_SecuritySignatures();

    // Open PDF document
    using (var document = new Aspose.Pdf.Document(dataDir + "blank.pdf"))
    {
        using (var pdfSign = new Aspose.Pdf.Facades.PdfFileSignature())
        {   
            // Bind PDF document
            pdfSign.BindPdf(document);

            // Sign with certificate selection in the windows certificate store
            var store = new X509Store(StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);
            // Manually chose the certificate in the store
            var sel = X509Certificate2UI.SelectFromCollection(store.Certificates, null, null, X509SelectionFlag.SingleSelection);
            
            // Set an external signature settings
            var externalSignature = new Aspose.Pdf.Forms.ExternalSignature(sel[0]);
            pdfSign.SignatureAppearance = dataDir + "demo.png";
            // Sign the document
            pdfSign.Sign(1, "Reason", "Contact", "Location", true, new System.Drawing.Rectangle(100, 100, 200, 200), externalSignature);
            // Save PDF document
            pdfSign.Save(dataDir + "externalSignature2_out.pdf");
        }
    }
}

private static void VerifyExternalSignature()
{
    // The path to the documents directory
    var dataDir = RunExamples.GetDataDir_AsposePdf_SecuritySignatures();

    // Open PDF document
    using (var document = new Aspose.Pdf.Document(dataDir + "externalSignature1.pdf"))
    {
        using (var pdfSign = new Aspose.Pdf.Facades.PdfFileSignature(document))
        {
            var sigNames = pdfSign.GetSignatureNames();
            for (int index = 0; index <= sigNames.Count - 1; index++)
            {
                if (!pdfSign.VerifySignature(sigNames[index]))
                {
                    throw new Exception("Not verified");
                }
            }
        }
    }
}

يمكنك استخدام فئة ExternalSignature لخدمة توقيع خارجية. تقوم ExternalSignature بإنشاء توقيعات PKCS7 وتوقيعات PKCS7 المنفصلة. يمكنك تمرير خوارزمية التجزئة المطلوبة إلى مُنشئ ExternalSignature. لاحظ أن التوقيعات غير المنفصلة يمكن أن تستخدم فقط SHA1. سيتم اختيارها تلقائيًا إذا لم تحدد خوارزمية التجزئة بشكل صريح. بالنسبة للتوقيعات غير المنفصلة، ستكون SHA1؛ بالنسبة للمنفصلة، ستكون SHA-256 لمفتاح RSA. بالنسبة لمفتاح ECDSA، يعتمد حجم التجزئة على حجم المفتاح.

يقبل مُنشئ ExternalSignature أيضًا شهادة مفتاح (يمكن أن تكون بتنسيق Base64). يمكنك تمرير شهادة تحتوي على مفتاح خاص وشهادة تحتوي فقط على مفتاح عام. في كلتا الحالتين، سيتم تنفيذ التوقيع خارجيًا في كود مفوض CustomSignHash، ولكن يجب أن تنشئ الخوارزمية الخارجية توقيعًا يتوافق مع مفتاح الشهادة الممررة. الشهادة مطلوبة لتوليد المستند الموقع بشكل صحيح. توقيع ECDSA لا يدعم SHA-1.

// For complete examples and data files, visit https://github.com/aspose-pdf/Aspose.PDF-for-.NET
private static void SignWithExternalService()
{    
    // The path to the documents directory
    var dataDir = RunExamples.GetDataDir_AsposePdf_SecuritySignatures();

    // Open PDF document
    using (var document = new Aspose.Pdf.Document(dataDir + "blank.pdf"))
    {
        using (var sign = new Aspose.Pdf.Facades.PdfFileSignature())
        {
            // Bind PDF document
            sign.BindPdf(document);

            // Get public certificate
            X509Certificate2 signerCert = GetPublicCertificate();

            // Set a certificate and a digest algorithm
            var signature = new Aspose.Pdf.Forms.ExternalSignature(signerCert, Aspose.Pdf.DigestHashAlgorithm.Sha256);

            // Define a delegate to external sign
            Aspose.Pdf.Forms.SignHash customSignHash = delegate(byte[] signableHash, Aspose.Pdf.DigestHashAlgorithm digestHashAlgorithm)
            {
                return CallExternalSignatureService(signableHash, digestHashAlgorithm);
            };
            // Set a sign hash
            signature.CustomSignHash = customSignHash;
            sign.Sign(1, "reason", "cont", "loc", false, new System.Drawing.Rectangle(0, 0, 500, 500), signature);
            // Save PDF document
            sign.Save(dataDir + "ExternalSignature_out.pdf");
        }
    }
}

private static X509Certificate2 GetPublicCertificate()
{
    // Your code to get a public certificate. The certificate can be supplied by a third-party service or a smart card
}

private static byte[] CallExternalSignatureService(byte[] hash, Aspose.Pdf.DigestHashAlgorithm digestHashAlgorithm)
{
    // Call a third-party service that provides a digital signature service
    // The method must return signed data
    // The digestHashAlgorithm argument points to the digest algorithm that was applied to the data to produce the value of the hash argument
}

لإنشاء توقيع، يلزم تقدير أولي لطول التوقيع الرقمي المستقبلي. إذا كنت تستخدم SignHash لإنشاء توقيع رقمي، قد تجد أن المفوض يتم استدعاؤه مرتين خلال عملية حفظ المستند. إذا لم تتمكن لأي سبب من تحمل استدعاءين، على سبيل المثال، إذا حدث طلب رمز PIN أثناء الاستدعاء، يمكنك استخدام خيار AvoidEstimatingSignatureLength لفئات PKCS1 وPKCS7 وPKCS7Detached وExternalSignature. يؤدي تعيين هذا الخيار إلى تجنب خطوة تقدير طول التوقيع عن طريق تعيين قيمة ثابتة كطول متوقع - DefaultSignatureLength. القيمة الافتراضية لخاصية DefaultSignatureLength هي 3000 بايت. يعمل خيار AvoidEstimatingSignatureLength فقط إذا تم تعيين مفوض SignHash في خاصية CustomSignHash. إذا تجاوز طول التوقيع الناتج الطول المتوقع المحدد بواسطة خاصية DefaultSignatureLength، ستتلقى SignatureLengthMismatchException تشير إلى الطول الفعلي. يمكنك ضبط قيمة معلمة DefaultSignatureLength حسب تقديرك.

بالنسبة لـ ExternalSignature، يمكن استخدام خيار AvoidEstimatingSignatureLength حتى إذا لم يتم استخدام CustomSignHash.

// For complete examples and data files, visit https://github.com/aspose-pdf/Aspose.PDF-for-.NET
private static void SignWithExternalService()
{    
    // The path to the documents directory
    var dataDir = RunExamples.GetDataDir_AsposePdf_SecuritySignatures();

    // Open PDF document
    using (var document = new Aspose.Pdf.Document(dataDir + "blank.pdf"))
    {
        using (var sign = new Aspose.Pdf.Facades.PdfFileSignature())
        {
            // Bind PDF document
            sign.BindPdf(document);

            // Get public certificate
            X509Certificate2 signerCert = GetPublicCertificate();

            // Set a certificate and a digest algorithm
            var signature = new Aspose.Pdf.Forms.ExternalSignature(signerCert, Aspose.Pdf.DigestHashAlgorithm.Sha256);

            // Define a delegate to external sign
            Aspose.Pdf.Forms.SignHash customSignHash = delegate(byte[] signableHash, Aspose.Pdf.DigestHashAlgorithm digestHashAlgorithm)
            {
                return CallExternalSignatureService(signableHash, digestHashAlgorithm);
            };
            // Set a sign hash
            signature.CustomSignHash = customSignHash;

            // Set an option to avoiding twice SignHash calling.
            signature.AvoidEstimatingSignatureLength = true;
            signature.DefaultSignatureLength = 3500;

            sign.Sign(1, "reason", "cont", "loc", false, new System.Drawing.Rectangle(0, 0, 500, 500), signature);
            // Save PDF document
            sign.Save(dataDir + "ExternalSignature_out.pdf");
        }
    }
}

private static X509Certificate2 GetPublicCertificate()
{
    // Your code to get a public certificate. The certificate can be supplied by a third-party service or a smart card
}

private static byte[] CallExternalSignatureService(byte[] hash, Aspose.Pdf.DigestHashAlgorithm digestHashAlgorithm)
{
    // Call a third-party service that provides a digital signature service
    // The method must return signed data
    // The digestHashAlgorithm argument points to the digest algorithm that was applied to the data to produce the value of the hash argument
}