Search Results for

    Show / Hide Table of Contents

    Signing PDFs (Delphi)

    Note

    This demo is available in your FlexCel installation at <FlexCel Install Folder>\Demo\Delphi\Modules\25.Printing and Exporting\35.Signing Pdfs and also at https:​//​github.​com/​tmssoftware/​TMS-​FlexCel.​VCL-​demos/​tree/​master/​Delphi/​Modules/​25.​Printing and Exporting/35.Signing Pdfs

    Overview

    In this example we will show how to add a visible or invisible signature to a generated PDF file.

    Concepts

    • In order to sign a PDF file you will need a certificate issued by a valid Certificate Authority, or one issued by yourself. In this example we will use a self signed certificate. This certificate will not validate by default when you open it in Acrobat, you need to add it to your trusted list.

    • As SHA-1 is deprecated, FlexCel will default to using SHA512 for the signature. You could use a different algorithm by providing an OID in the EncryptionFactory.GetSigner call.

    • In order to sign a file, FlexCel will write a requirement for Acrobat 8 or newer in the generated files. This is because only Acrobat 8 or newer support SHA512. Older versions of acrobat will still display the pages but will not validate the signature.

    • FlexCel currently only has support for signing in Windows, using CryptoAPI. You can still create your own signature engine for other platforms by using a third party cryptography library or by calling the native crypto functions in that platform, the same way we call CryptoAPI. This is explained in the section Signing PDF Files in the PDF exporting guide.

    Files

    USigningPdfs.pas

    unit USigningPdfs;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Variants, Classes, Graphics,
      Controls, Forms, Dialogs,
      StdCtrls,
      pngimage, ExtCtrls, ExtDlgs,
      {$if CompilerVersion >= 23.0} System.UITypes, {$IFEND}
      FlexCel.VCLSupport, FlexCel.Core, FlexCel.XlsAdapter, FlexCel.Render, FlexCel.Pdf;
    
    
    type
      TFSigningPdfs = class(TForm)
        btnCreateAndSignPdf: TButton;
        cbVisibleSignature: TCheckBox;
        SignaturePicture: TImage;
        OpenPictureDialog: TOpenPictureDialog;
        OpenExcelDialog: TOpenDialog;
        SavePdfDialog: TSaveDialog;
        procedure cbVisibleSignatureClick(Sender: TObject);
        procedure SignaturePictureClick(Sender: TObject);
        procedure btnCreateAndSignPdfClick(Sender: TObject);
        procedure FormCreate(Sender: TObject);
      private
        DataPath: string;
        ImgData: ByteArray;
        procedure LoadImage(const FileName: string);
    
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      FSigningPdfs: TFSigningPdfs;
    
    implementation
    uses IOUtils, UFlexCelHDPI, ShellAPI;
    
    {$R *.dfm}
    procedure TFSigningPdfs.LoadImage(const FileName: string);
    begin
      ImgData := TFile.ReadAllBytes(FileName);
      SignaturePicture.Picture.LoadFromFile(FileName);
    end;
    
    procedure TFSigningPdfs.FormCreate(Sender: TObject);
    begin
      DataPath := TPath.Combine(TPath.GetDirectoryName(ParamStr(0)), '..\..\');
      LoadImage(DataPath + 'sign.png');
    end;
    
    
    procedure TFSigningPdfs.btnCreateAndSignPdfClick(Sender: TObject);
    var
      xls: TExcelFile;
      pdf: TFlexCelPdfExport;
      Cert: TX509Certificate2;
      Signer: TCmsSigner;
      Signature: TPdfSignature;
    
    begin
      //Load the Excel file.
      if (not OpenExcelDialog.Execute) then exit;
      xls := TXlsFile.Create;
      try
        xls.Open(OpenExcelDialog.FileName);
    
        //Export it to pdf.
        pdf := TFlexCelPdfExport.Create(xls, true);
        try
          pdf.FontEmbed := TFontEmbed.Embed;
    
          //Load the certificate and create a signer.
          Cert := EncryptionFactory.GetX509Certificate(TFile.ReadAllBytes(DataPath + 'flexcel.pfx'), 'password');
          try
            // The current implementation uses only one certificate. The algorithm by
            // default if you leave the second parameter empty is SHA512.
            Signer := EncryptionFactory.GetSigner(TArray<TX509Certificate2>.Create(Cert), '');
            try
              if (cbVisibleSignature.Checked) then
              begin
                //The -1 as "page" parameter means the last page.
                Signature := TPdfVisibleSignature.Create(TBuiltInSignerFactory.Create(Signer),
                                'Signature',
                                'I have read the document and certify it is valid.',
                                'Springfield',
                                'adrian@tmssoftware.com',
                                -1,
                                TUIRectangle.Create(50, 50, 140, 70),
                                ImgData);
                Signer := nil; //The signature now owns the Signer so we don't want to free it.
    
    
    
              end
              else
              begin
                Signature := TPdfSignature.Create(TBuiltInSignerFactory.Create(Signer),
                                              'Signature',
                                              'I have read the document and certify it is valid.',
                                              'Springfield',
                                              'adrian@tmssoftware.com');
                Signer := nil; //The signature now owns the Signer so we don't want to free it.
              end;
            Except
              Signer.Free;  //Only if there is an error.
              raise;
            end;
    
            //You must sign the document *BEFORE* starting to write it.
            pdf.Sign(Signature); //Now the pdf owns the signature. There is no need to free it.
    
            if (not SavePdfDialog.Execute) then exit;
            pdf.ExportAllVisibleSheets(SavePdfDialog.FileName, false, 'Signed Pdf');
          finally
            Cert.Free;
          end;
        finally
          pdf.Free;
        end;
      finally
        xls.Free;
      end;
    
      if MessageDlg('Do you want to open the generated file?', mtConfirmation, [mbYes, mbNo], 0) = mrYes then
      begin
        ShellExecute(0, 'open', PCHAR(SavePdfDialog.FileName), nil, nil, SW_SHOWNORMAL);
      end;
    
    end;
    
    procedure TFSigningPdfs.cbVisibleSignatureClick(Sender: TObject);
    var
      delta: integer;
    begin
      SignaturePicture.Visible := cbVisibleSignature.Checked;
      Delta := SignaturePicture.Height + 30;
      if (cbVisibleSignature.Checked) then Height := Height + delta else Height := Height - delta;
    end;
    
    procedure TFSigningPdfs.SignaturePictureClick(Sender: TObject);
    begin
      if (not OpenPictureDialog.Execute) then exit;
      LoadImage(OpenPictureDialog.FileName);
    end;
    
    end.
    
    In This Article
    Back to top FlexCel Studio for VCL and FireMonkey v7.24
    © 2002 - 2025 tmssoftware.com