إضافة توقيع رقمي أو توقيع PDF رقمياً في C#

Aspose.PDF for .NET يدعم ميزة توقيع ملفات PDF رقمياً باستخدام الفئة SignatureField. يمكنك أيضاً تصديق ملف PDF باستخدام شهادة PKCS12. شيء مشابه لـ Adding Signatures and Security in Adobe Acrobat.

عند توقيع مستند PDF باستخدام توقيع، فأنت في الأساس تؤكد محتوياته “كما هي”. وبالتالي، أي تغييرات أخرى تُجرى لاحقاً تُلغي صحة التوقيع، وبالتالي ستعرف إذا تم تعديل المستند. بينما يسمح لك تصديق المستند أولاً بتحديد التغييرات التي يمكن للمستخدم إجراؤها على المستند دون إبطال الشهادة.

بمعنى آخر، سيظل المستند يُعتبر محافظاً على سلامته ويمكن للمستلم الثقة به. لمزيد من التفاصيل، يرجى زيارة Certifying and signing a PDF. بشكل عام، يمكن مقارنة تصديق المستند بتوقيع شفرة تنفيذية .NET.

الكود التالي يعمل أيضاً مع مكتبة Aspose.PDF.Drawing.

ميزات توقيع Aspose.PDF for .NET

يمكننا استخدام الفئات والطرق التالية لتوقيع PDF

لإنشاء توقيع رقمي يعتمد على شهادات PKCS12 (امتدادات الملفات .p12, .pfx)، يجب إنشاء مثيل من الفئة PdfFileSignature وتمرير كائن المستند إليها. بعد ذلك، يجب تحديد طريقة التوقيع الرقمي المطلوبة بإنشاء كائن من إحدى الفئات التالية:

  • PKCS1.
  • PKCS7.
  • PKCS7Detached.

يمكنك ضبط خوارزمية التجزئة فقط لـ PKCS7Detached. بالنسبة إلى PKCS1 و PKCS7، تكون خوارزمية التجزئة دائماً SHA-1.

بعد ذلك، تحتاج إلى استخدام كائن خوارزمية التوقيع المستلمة في طريقة PdfFileSignature.Sign(). سيتم تعيين التوقيع الرقمي للمستند بعد حفظه.

توقيع PDF بالتواقيع الرقمية

المثال أدناه ينشئ توقيع PKCS7 غير منفصل مع خوارزمية تجزئة SHA-1.

// For complete examples and data files, visit https://github.com/aspose-pdf/Aspose.PDF-for-.NET
private static void SignDocument()
{
    // The path to the documents directory
    var dataDir = RunExamples.GetDataDir_AsposePdf_SecuritySignatures();
    
    // Open PDF document
    using (var document = new Aspose.Pdf.Document(dataDir + "DigitallySign.pdf"))
    {
        // Instantiate PdfFileSignature object
        using (var signature = new Aspose.Pdf.Facades.PdfFileSignature(document))
        {
            // Create PKCS#7 object for sign
            var pkcs = new Aspose.Pdf.Forms.PKCS7(dataDir + "rsa_cert.pfx", "12345");
            // Sign PDF file
            signature.Sign(1, true, new System.Drawing.Rectangle(300, 100, 400, 200), pkcs);
            // Save PDF document
            signature.Save(dataDir + "DigitallySign_out.pdf");
        }
    }
}

المثال أدناه ينشئ توقيعاً منفصلاً بصيغة PKCS7Detached مع خوارزمية تجزئة SHA-256. تعتمد خوارزمية المفتاح على مفتاح الشهادة. يتم دعم DSA و RSA و ECDSA.

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

    // Open PDF document
    using (var document = new Aspose.Pdf.Document(dataDir + "DigitallySign.pdf"))
    {
        // Instantiate PdfFileSignature object using the opened document
        using (var signature = new Aspose.Pdf.Facades.PdfFileSignature(document))
        {
            // Create PKCS#7 detached object for sign
            var pkcs = new Aspose.Pdf.Forms.PKCS7Detached(pfxFilePath, password, Aspose.Pdf.DigestHashAlgorithm.Sha256);
            // Sign PDF file
            signature.Sign(1, true, new System.Drawing.Rectangle(300, 100, 400, 200),pkcs);
            // Save PDF document
            signature.Save(dataDir + "DigitallySign_out.pdf");
        }
    }
}

يمكنك التحقق من التواقيع باستخدام طريقة PdfFileSignature.VerifySignature(). سابقاً، كانت طريقة GetSignNames() تُستخدم للحصول على أسماء التواقيع. بدءاً من الإصدار 25.02، يجب استخدام طريقة GetSignatureNames() التي تُعيد قائمة من SignatureName. تُجنب SignatureName حدوث تصادمات عند التحقق من التواقيع التي تحمل نفس الأسماء. يجب أيضاً استخدام الطرق التي تقبل النوع SignatureName بدلاً من اسم التوقيع كسلسلة نصية.

ملاحظة، طريقة PdfFileSignature.VerifySigned() مهجورة.

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

    // Open PDF document
    using (var document = new Aspose.Pdf.Document(dataDir + "signed_rsa.pdf"))
    {
        // Create an instance of PdfFileSignature for working with signatures in the document
        using (var signature = new Aspose.Pdf.Facades.PdfFileSignature(document))
        {         
            // Get a list of signature names in the document
            var sigNames = signature.GetSignatureNames();

            // Loop through all signature names to verify each one
            foreach (var sigName in sigNames)
            {
                // Verify that the signature with the given name is valid
                if (!signature.VerifySignature(sigName))
                {
                    throw new Exception("Not verified");
                }
            }
        }
    }
}

التحقق من التواقيع الرقمية باستخدام شهادة مفتاح عام خارجية

يمكنك استخدام شهادة خارجية تحتوي على المفتاح العام الذي يتطابق مع المفتاح الخاص المستخدم لتوقيع المستند للتحقق من التوقيع.

يمكنك استخراج شهادة من التوقيع واستخدامها للتحقق من التوقيع.

التحقق من التواقيع الرقمية مع فحص الشهادة

عند التحقق من توقيع رقمي، يمكنك فحص شهادة التوقيع للتحقق من إلغائها.

للأسف، لا يمكن لـ Aspose.PDF التحقق من أصالة الشهادات الجذرية أو الوسيطة في سلسلة الشهادات. لذلك، يتم فحص حالة إلغاء شهادة التوقيع فقط باستخدام CRL و OCSP.

لتكوين التحقق من الشهادة، يمكنك استخدام معامل ValidationOptions.

خيار ValidationMode يقدم ثلاث أوضاع للتحقق:

  • None – لا يتم فحص الشهادة.
  • Strict – إلغاء الشهادة يؤثر على نتيجة طريقة Verify.
  • OnlyCheck – يسمح بفحص الشهادة دون التأثير على نتيجة التحقق من التوقيع.

الخيار ValidationMethod يحدد الطريقة المستخدمة لفحص الشهادة:

  • Auto – اختيار تلقائي للطريقة. يُفضَّل OCSP. يتم تحديد حالة الإلغاء بناءً على الطريقة التي تُجري الفحص بنجاح.
  • Ocsp – يتم فحص الإلغاء باستخدام OCSP.
  • Crl – يتم فحص الإلغاء باستخدام CRL.
  • All – تُستخدم الطريقتان لفحص الشهادة. لكي ينجح التحقق، يجب أن تؤكد كلتا الطريقتين أن الشهادة غير مُلغاة.

الخيار CheckCertificateChain يتيح فحص وجود سلسلة شهادات في التوقيع. إذا لم تُعثر على سلسلة الشهادات، ستكون نتيجة التحقق من الشهادة Undefined.

يمكن الحصول على نتيجة الفحص عبر معامل إخراج من النوع ValidationResult. الحالات الممكنة هي: Valid، Invalid، و Undefined. عادةً ما يعني Undefined أن الشهادة لم يمكن التحقق منها أو أن سلسلة الشهادات مفقودة.

تعيين كل من CheckCertificateChain و ValidationMode = ValidationMode.Strict يُطابق سلوك Adobe Acrobat. إذا لم يتمكن Adobe Acrobat من العثور على سلسلة الشهادات، فإنه لا يفحص حالة الإلغاء، ويُعتبر التوقيع غير صالح.

إضافة طابع زمني إلى التوقيع الرقمي

كيفية توقيع PDF رقمياً مع طابع زمني

Aspose.PDF for .NET يدعم توقيع PDF رقمياً باستخدام خادم طابع زمني أو خدمة ويب.

لتحقيق هذا المتطلب، تمت إضافة الفئة TimestampSettings إلى مساحة أسماء Aspose.PDF. يرجى إلقاء نظرة على المقتطف التالي الذي يحصل على طابع زمني ويضيفه إلى مستند PDF:

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

    // Open PDF document
    using (var document = new Aspose.Pdf.Document(dataDir + "SimpleResume.pdf"))
    {
        // Create an instance of PdfFileSignature for working with signatures in the document
        using (var signature = new Aspose.Pdf.Facades.PdfFileSignature(document))
        {
            // Create TimestampSettings settings
            var timestampSettings = new Aspose.Pdf.TimestampSettings("https://freetsa.org/tsr", string.Empty); // User/Password can be omitted
            var pkcs = new Aspose.Pdf.Forms.PKCS7(timestampSettings);       
           
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(100, 100, 200, 100);
            // Create any of the three signature types
            signature.Sign(1, "Signature Reason", "Contact", "Location", true, rect, pkcs);
            // Save PDF document
            signature.Save(dataDir + "DigitallySignWithTimeStamp_out.pdf");
        }
    }
}
// For complete examples and data files, visit https://github.com/aspose-pdf/Aspose.PDF-for-.NET
private static void SignWithEmbeddedTimestamp(string pfxFilePath, string password)
{    
    // The path to the documents directory
    var dataDir = RunExamples.GetDataDir_AsposePdf_SecuritySignatures();

    // Open PDF document
    using (var document = new Aspose.Pdf.Document(dataDir + "SimpleResume.pdf"))
    {
        // Create an instance of PdfFileSignature for working with signatures in the document
        using (var signature = new Aspose.Pdf.Facades.PdfFileSignature(document))
        {
            var pkcs = new Aspose.Pdf.Forms.PKCS7(pfxFilePath, password);
            // Create TimestampSettings settings
            var timestampSettings = new Aspose.Pdf.TimestampSettings("https://freetsa.org/tsr", string.Empty); // User/Password can be omitted
            pkcs.TimestampSettings = timestampSettings;
            System.Drawing.Rectangle rect = new System.Drawing.Rectangle(100, 100, 200, 100);
            // Create any of the three signature types
            signature.Sign(1, "Signature Reason", "Contact", "Location", true, rect, pkcs);
            // Save PDF document
            signature.Save(dataDir + "DigitallySignWithTimeStamp_out.pdf");
        }
    }
}

توقيع PDF باستخدام X509Certificate2 بصيغة base64

هذا الكود يوقع PDF باستخدام شهادة خارجية، وربما يتفاعل مع خادم لاسترجاع التجزئة الموقعة وتضمين التوقيع في مستند PDF.

خطوات توقيع PDF:

  1. إنشاء مثيل من PdfFileSignature.
  2. تعريف تجزئة التوقيع المخصصة.
  3. تحميل الشهادة.
  4. توقيع البيانات.
  5. ربط وتوقيع PDF.
  6. حفظ PDF الموقّع.
// For complete examples and data files, visit https://github.com/aspose-pdf/Aspose.PDF-for-.NET
private static void SignWithBase64Certificate(string pfxFilePath, string password)
{
    // The path to the documents directory
    var dataDir = RunExamples.GetDataDir_AsposePdf_SecuritySignatures();

    var base64Str = "Certificate in base64 format";
    using (var pdfSign = new Aspose.Pdf.Facades.PdfFileSignature())
    {
        var sign = new Aspose.Pdf.Forms.ExternalSignature(base64Str, false);// without Private Key
        sign.ShowProperties = false;
        // Create a delegate to external sign
        Aspose.Pdf.Forms.SignHash customSignHash = delegate (byte[] signableHash, Aspose.Pdf.DigestHashAlgorithm digestHashAlgorithm)
        {
            // Simulated Server Part (This will probably just be sending data and receiving a response)
            var signerCert = new X509Certificate2(pfxFilePath, password, X509KeyStorageFlags.Exportable);// must have Private Key
            var rsaCSP = new RSACryptoServiceProvider();
            var xmlString = signerCert.PrivateKey.ToXmlString(true);
            rsaCSP.FromXmlString(xmlString);
            byte[] signedData = rsaCSP.SignData(signableHash, CryptoConfig.MapNameToOID("SHA1"));
            return signedData;
        };
        sign.CustomSignHash = customSignHash;
        // Bind PDF document
        pdfSign.BindPdf(dataDir + "input.pdf");
        // Sign the file
        pdfSign.Sign(1, "second approval", "second_user@example.com", "Australia", false,
            new System.Drawing.Rectangle(200, 200, 200, 100),
            sign);
        // Save PDF document
        pdfSign.Save(dataDir + "SignWithBase64Certificate_out.pdf");
    }
}

توقيع PDF باستخدام دالة توقيع تجزئة مخصصة

باستخدام دالة توقيع تجزئة مخصصة، يمكن لسلطة التوقيع تنفيذ معايير تشفيرية محددة أو سياسات أمان داخلية تتجاوز طرق التوقيع القياسية، مما يضمن سلامة المستند. يساعد هذا النهج على التحقق من أن المستند لم يتغير منذ تطبيق التوقيع ويوفر توقيعاً رقمياً ملزماً قانونياً مع دليل قابل للتحقق على هوية المُوقّع باستخدام شهادة PFX.

هذا المقتطف يوضح توقيع مستند PDF رقمياً باستخدام شهادة PFX (PKCS#12) مع دالة توقيع تجزئة مخصصة في C#.

دعونا نلقي نظرة أقرب على عملية توقيع PDF:

  1. تعريف مسارات الملفات ومعلومات الشهادة:
  • inputPdf: مسار ملف PDF الإدخالي الذي يحتاج إلى توقيع.
  • inputP12: مسار ملف شهادة .p12 (PFX) المستخدم للتوقيع.
  • inputPfxPassword: كلمة مرور شهادة PFX.
  • outputPdf: المسار الذي سيُحفظ فيه ملف PDF الموقّع.
  1. عملية التوقيع:
  • يتم إنشاء كائن PdfFileSignature وربطه بملف PDF الإدخالي.
  • يتم تهيئة كائن PKCS7 باستخدام شهادة PFX وكلمة مرورها. تُعيّن طريقة CustomSignHash كدالة توقيع تجزئة مخصصة.
  • تُستدعى طريقة Sign مع تحديد رقم الصفحة (1 في هذا المثال)، وتفاصيل التوقيع (السبب، الاتصال، الموقع)، وموقع التوقيع (مستطيل بالإحداثيات (0, 0, 500, 500)).
  • يُحفظ ملف PDF الموقّع في المسار المحدد.
  1. توقيع التجزئة المخصص:
  • تستقبل طريقة CustomSignHash مصفوفة بايت signableHash (التجزئة القابلة للتوقيع).
  • تُحمّل نفس شهادة PFX وتستخرج المفتاح الخاص منها.
  • يُستخدم المفتاح الخاص لتوقيع التجزئة باستخدام RSACryptoServiceProvider وخوارزمية SHA-1.
  • تُرجع البيانات الموقّعة (مصفوفة بايت) لتُطبق على توقيع PDF.

يمكن تحديد خوارزمية التجزئة في مُنشئ PKCS7Detached. يمكن استدعاء خدمة طرف ثالث داخل تفويض CustomSignHash. يجب أن تتطابق خوارزمية التوقيع المستخدمة في CustomSignHash مع خوارزمية المفتاح في الشهادة الممررة إلى PKCS7/PKCS7Detached.

المثال أدناه ينشئ توقيعاً غير منفصل باستخدام خوارزمية RSA وخوارزمية تجزئة SHA-1. إذا استخدمت PKCS7Detached بدلاً من PKCS7، يمكنك استخدام ECDCA وتحديد خوارزمية التجزئة المطلوبة.

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

    using (var sign = new Aspose.Pdf.Facades.PdfFileSignature())
    {   
        // Bind PDF document
        sign.BindPdf(dataDir + "input.pdf");
        // Create PKCS#7 object to sign
        var pkcs7 = new Aspose.Pdf.Forms.PKCS7(pfxFilePath, password);// You can use PKCS7Detached with digest algorithm argument
        // Set the delegate to external sign
        pkcs7.CustomSignHash = CustomSignHash;
        // Sign the file
        sign.Sign(1, "reason", "cont", "loc", false, new System.Drawing.Rectangle(0, 0, 500, 500), pkcs7);
        // Save PDF document
        sign.Save(dataDir + "SignWithCertificate_out.pdf");
    }

    // Custom hash signing function to generate a digital signature
    byte[] CustomSignHash(byte[] signableHash, Aspose.Pdf.DigestHashAlgorithm digestHashAlgorithm)
    {
        var inputP12 = "111.p12";
        var inputPfxPassword = "123456";
        X509Certificate2 signerCert = new X509Certificate2(inputP12, inputPfxPassword, X509KeyStorageFlags.Exportable);
        RSACryptoServiceProvider rsaCSP = new RSACryptoServiceProvider();
        var xmlString = signerCert.PrivateKey.ToXmlString(true);
        rsaCSP.FromXmlString(xmlString);
        byte[] signedData = rsaCSP.SignData(signableHash, CryptoConfig.MapNameToOID("SHA1"));
        return signedData;
    }
}

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

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

    using (var sign = new Aspose.Pdf.Facades.PdfFileSignature())
    {   
        // Bind PDF document
        sign.BindPdf(dataDir + "input.pdf");
        // Create PKCS#7 object to sign
        var pkcs7 = new Aspose.Pdf.Forms.PKCS7(pfxFilePath, password);// You can use PKCS7Detached with digest algorithm argument
        // Set the delegate to external sign
        pkcs7.CustomSignHash = CustomSignHash;
        // Set an option to avoiding twice SignHash calling.
        pkcs7.AvoidEstimatingSignatureLength = true;
        // Sign the file
        sign.Sign(1, "reason", "cont", "loc", false, new System.Drawing.Rectangle(0, 0, 500, 500), pkcs7);
        // Save PDF document
        sign.Save(dataDir + "SignWithCertificate_out.pdf");
    }

    // Custom hash signing function to generate a digital signature
    byte[] CustomSignHash(byte[] signableHash, Aspose.Pdf.DigestHashAlgorithm digestHashAlgorithm)
    {
        var inputP12 = "111.p12";
        var inputPfxPassword = "123456";
        X509Certificate2 signerCert = new X509Certificate2(inputP12, inputPfxPassword, X509KeyStorageFlags.Exportable);
        RSACryptoServiceProvider rsaCSP = new RSACryptoServiceProvider();
        var xmlString = signerCert.PrivateKey.ToXmlString(true);
        rsaCSP.FromXmlString(xmlString);
        byte[] signedData = rsaCSP.SignData(signableHash, CryptoConfig.MapNameToOID("SHA1"));
        return signedData;
    }
}

توقيع مستندات PDF باستخدام ECDSA

يتضمن توقيع مستندات PDF باستخدام ECDSA (Elliptic Curve Digital Signature Algorithm) الاستفادة من تشفير المنحنيات الإهليلجية لإنشاء توقيعات رقمية. يوفر هذا أماناً عالياً وكفاءة، خاصةً في البيئات المتنقلة ومحدودة الموارد. يضمن هذا النهج أن تكون مستندات PDF موقعة رقمياً مع مزايا الأمان لتشفير المنحنيات الإهليلجية.

Aspose.PDF يدعم إنشاء وتحقق التوقيعات الرقمية القائمة على ECDSA. المنحنيات الإهليلجية التالية مدعومة لإنشاء وتحقق التواقيع الرقمية:

  • P-192(secp192r1).
  • P-256(secp256r1).
  • P-384(secp384r1).
  • P-521(secp521r1).
  • brainpoolP192r1.
  • brainpoolP256r1.
  • brainpoolP384r1.
  • brainpoolP512r1.

الخوارزمية الافتراضية للتجزئة هي SHA2 بطول يعتمد على حجم مفتاح ECDSA. يمكنك تحديد خوارزمية التجزئة في مُنشئ PKCS7Detached.

يمكن توقيع التواقيع الرقمية ECDSA بالخوارزميات التالية: SHA-256، SHA-384، SHA3–512، SHA3–256، SHA3–384، SHA3–512. يمكن التحقق من التواقيع الرقمية ECDSA بالخوارزميات نفسها.

يمكنك التحقق من التوقيع والتحقق بإنشاء شهادة PFX (output.pfx) باستخدام OpenSSL.

openssl ecparam -genkey -name brainpoolP512r1 -out private.key
openssl ec -in private.key -pubout -out public.pem
openssl req -new -x509 -days 365 -key private.key -out certificate.crt -subj "/C=PL/ST=Silesia/L=Katowice/O=My2 Organization/CN=example2.com"
openssl pkcs12 -export -out output.pfx -inkey private.key -in certificate.crt

أسماء المنحنيات المتاحة للتوقيع والتحقق في Aspose.PDF (قائمة المنحنيات في OpenSSL يمكن الحصول عليها بالأمر openssl ecparam -list_curves): prime256v1، secp384r1، secp521r1، brainpoolP256r1، brainpoolP384r1، brainpoolP512r1.

لتوقيع مستند PDF باستخدام ECDSA، الخطوات العامة في C# هي:

  1. سيتطلب الأمر شهادة ECDSA بصيغة PFX أو P12. تحتوي هذه الشهادات على المفتاحين العام والخاص اللازمين للتوقيع.
  2. باستخدام مكتبة Aspose.PDF، تقوم بربط المستند بمعالج التوقيع.
  3. تستخدم المفتاح الخاص ECDSA لتوقيع تجزئة محتوى المستند.
  4. تضع التوقيع المُولد داخل ملف PDF مع بيانات وصفية مثل سبب التوقيع، الموقع، وتفاصيل الاتصال.
// For complete examples and data files, visit https://github.com/aspose-pdf/Aspose.PDF-for-.NET
private static void VerifyEcda()
{
   // The path to the documents directory
   var dataDir = RunExamples.GetDataDir_AsposePdf_SecuritySignatures();

   // Open PDF document
   using (var document = new Aspose.Pdf.Document(dataDir + "signed_ecdsa.pdf"))
    {
        // Create an instance of PdfFileSignature for working with signatures in the document
        using (var signature = new Aspose.Pdf.Facades.PdfFileSignature(document))
        {
            // Check if the document contains any digital signatures
            if (!signature.ContainsSignature())
            {
                throw new Exception("Not contains signature");
            }

            // Get a list of signature names in the document
            var sigNames = signature.GetSignatureNames();

            // Loop through all signature names to verify each one
            foreach (var sigName in sigNames)
            {
                // Verify that the signature with the given name is valid
                if (!signature.VerifySignature(sigName))
                {
                    throw new Exception("Not verified");
                }
            }
        }
    }
}

private static void SignEcdsa(string pfxFilePath, string password)
{
    // The path to the documents directory
    var dataDir = RunExamples.GetDataDir_AsposePdf_SecuritySignatures(); 

    // Open PDF document
    using (var document = new Aspose.Pdf.Document(dataDir + "input.pdf"))
    {
        // Create an instance of PdfFileSignature to sign the document
        using (var signature = new Aspose.Pdf.Facades.PdfFileSignature(document))
        {
            // Create a PKCS7Detached object using the provided certificate and password
            var pkcs = new Aspose.Pdf.Forms.PKCS7Detached(cert, "12345", Aspose.Pdf.DigestHashAlgorithm.Sha256);

            // Sign the first page of the document, setting the signature's appearance at the specified location
            signature.Sign(1, true, new System.Drawing.Rectangle(300, 100, 400, 200), pkcs);

            // Save PDF document
            signature.Save(dataDir + "SignEcdsa_out.pdf");
        }
    }
}