Examples / signed_pdfa / csharp

Signed Pdfa

A complete, runnable csharp program — 123 lines, shipped in your download.

Demonstrates Digital Signatures

Same example, other languages: activex_cpp c cpp cpp_linux python vbnet

examples/csharp/signed_pdfa/signed_pdfa.cs 123 lines
//  signed_pdfa -- C# port of examples\Vb6\signed_pdfa\signed_pdfa.bas
//  Creates a PDF/A-1b compatible file with a digitally-signed signature field,
//  checks conformance, adds the matching output intent, then signs the file
//  with a self-signed certificate.
using System;
using System.IO;
using LumasPdfSdk;

class SignedPDFA
{
    static uint RGB(int r, int g, int b)
    {
        return (uint)(r | (g << 8) | (b << 16));
    }

    // We try to continue if an error occurs
    static int ErrProc(IntPtr Data, int ErrCode, string ErrMessage, int ErrType)
    {
        Console.WriteLine(ErrMessage);
        return 0;
    }

    static TErrorProc _errCb = ErrProc;

    static void Main()
    {
        string cr = "\r";
        string tf = System.IO.Path.Combine(System.AppContext.BaseDirectory, "..", "..", "..", "..", "test_files");

        IntPtr pdf = LumasPdf.pdfNewPDF();
        LumasPdf.pdfCreateNewPDFW(pdf, "");        // The output file is opened later
        LumasPdf.pdfSetOnErrorProc(pdf, IntPtr.Zero, _errCb);

        LumasPdf.pdfAppend(pdf);
        LumasPdf.pdfSetFontW(pdf, "Arial", LumasPdfConsts.fsNone, 10.0, true, TCodepage.cp1252);
        string body = "This is a PDF/A 1b compatible PDF file that was digitally signed with " +
            "a self sign certificate. Because PDF/A requires that all fonts are embedded it is important " +
            "to avoid the usage of the 14 Standard fonts." + cr + cr +
            "When signing a PDF/A compliant PDF file with the default settings (without creation of a user " +
            "defined appearance) the font Arial must be available on the system because it is used to print " +
            "the certificate properties into the signature field." + cr + cr +
            "The font Arial must also be available if an empty signature field was added to the file " +
            "without signing it when closing the PDF file. Yes, it is still possible to sign a PDF/A " +
            "compliant PDF file later with Adobe's Acrobat. The signed PDF file is still compatible " +
            "to PDF/A. If you use a third party solution to digitally sign the PDF file then test " +
            "whether the signed file is still valid with the PDF/A 1b preflight tool included in Acrobat 8 " +
            "Professional." + cr + cr +
            "Signature fields must be visible and the print flag must be set (default). CheckConformance() " +
            "adjusts these flags if necessary and produces a warning if changes were applied. If no changes " +
            "should be allowed, just return -1 in the error callback function. If the error callback function " +
            "returns 0, LumasPDF assumes that the prior changes were accepted and processing continues." + cr + cr +
            "\\FC[255]Notice:\\FC[0]" + cr +
            "It makes no sense to execute CheckConformance() without an error callback function or error event " +
            "in VB. If you cannot see what happens during the execution of CheckConformance(), it is " +
            "completely useless to use this function!" + cr + cr +
            "CheckConformance() should be used to find the right settings to create PDF/A compatible PDF files. " +
            "Once the the settings were found it is usually not longer recommended to execute this function. " +
            "However, it is of course possible to use CheckConformance() as a general approach to make sure " +
            "that files created with the classic API are PDF/A compatible.";
        LumasPdf.pdfWriteFTextW(pdf, LumasPdfConsts.taLeft, body);

        // ---------------------- Signature field appearance ----------------------
        int sigField = LumasPdf.pdfCreateSigField(pdf, "Signature", -1, 200.0, 400.0, 200.0, 80.0);
        LumasPdf.pdfSetFieldColor(pdf, (uint)sigField, (int)TFieldColor.fcBorderColor, (int)TPDFColorSpace.csDeviceRGB, LumasPdfConsts.NO_COLOR);
        LumasPdf.pdfPlaceSigFieldValidateIcon(pdf, (uint)sigField, 0.0, 15.0, 50.0, 50.0);
        LumasPdf.pdfCreateSigFieldAP(pdf, (uint)sigField);

        LumasPdf.pdfSaveGraphicState(pdf);
        LumasPdf.pdfRectangle(pdf, 0.0, 0.0, 200.0, 80.0, (int)TPathFillMode.fmNoFill);
        LumasPdf.pdfClipPath(pdf, TClippingMode.cmWinding, TPathFillMode.fmNoFill);
        int sh = LumasPdf.pdfCreateAxialShading(pdf, 0.0, 0.0, 200.0, 0.0, 0.5, RGB(120, 120, 220), RGB(255, 255, 255), 1, 1);
        LumasPdf.pdfApplyShading(pdf, sh);
        LumasPdf.pdfRestoreGraphicState(pdf);

        LumasPdf.pdfSaveGraphicState(pdf);
        LumasPdf.pdfEllipse(pdf, 50.5, 1.0, 148.5, 78.0, (int)TPathFillMode.fmNoFill);
        LumasPdf.pdfClipPath(pdf, TClippingMode.cmWinding, TPathFillMode.fmNoFill);
        sh = LumasPdf.pdfCreateAxialShading(pdf, 0.0, 0.0, 0.0, 78.0, 2.0, RGB(255, 255, 255), RGB(120, 120, 220), 1, 1);
        LumasPdf.pdfApplyShading(pdf, sh);
        LumasPdf.pdfRestoreGraphicState(pdf);

        LumasPdf.pdfSetFontW(pdf, "Arial", LumasPdfConsts.fsBold | LumasPdfConsts.fsUnderlined, 11.0, true, TCodepage.cp1252);
        LumasPdf.pdfSetFillColor(pdf, RGB(120, 120, 220));
        LumasPdf.pdfWriteFTextExW(pdf, 50.0, 60.0, 150.0, -1.0, (int)LumasPdfConsts.taCenter, "Digitally signed by:");
        LumasPdf.pdfSetFontW(pdf, "Arial", LumasPdfConsts.fsBold | LumasPdfConsts.fsItalic, 18.0, true, TCodepage.cp1252);
        LumasPdf.pdfSetFillColor(pdf, RGB(100, 100, 200));
        LumasPdf.pdfWriteFTextExW(pdf, 50.0, 45.0, 150.0, -1.0, (int)LumasPdfConsts.taCenter, "LumasPDF");

        LumasPdf.pdfEndTemplate(pdf);              // Close the appearance template.
        // ------------------------------------------------------------------------

        LumasPdf.pdfEndPage(pdf);
        // Check whether the file is compatible to PDF/A 1b.
        switch (LumasPdf.pdfCheckConformance(pdf, (int)TConformanceType.ctPDFA_1b_2005, 0, IntPtr.Zero, null, null))
        {
            case 1:
            case 3:
                LumasPdf.pdfAddOutputIntentW(pdf, tf + "sRGB.icc");             // Gray, RGB
                break;
            case 2:
                LumasPdf.pdfAddOutputIntentW(pdf, tf + "ISOcoated_v2_bas.ICC"); // CMYK
                break;
        }

        string outFile = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "out.pdf");
        // No fatal error occurred?
        if (LumasPdf.pdfHaveOpenDoc(pdf))
        {
            if (!LumasPdf.pdfOpenOutputFileW(pdf, outFile))
            {
                LumasPdf.pdfDeletePDF(pdf);
                return;
            }
        }
        // Original certificate ..\..\test_files\test_cert.pfx
        string certFile = System.IO.Path.Combine(System.AppContext.BaseDirectory, "..", "..", "..", "..", "test_files") + "\\test_cert.pfx";
        if (LumasPdf.pdfCloseAndSignFile(pdf, certFile, "123456", "Test", ""))
            Console.WriteLine("PDF file \"" + outFile + "\" successfully created!");

        LumasPdf.pdfDeletePDF(pdf);
    }
}

This file is in the SDK at examples/csharp/signed_pdfa/signed_pdfa.cs. The build fails if this page and that file ever differ.