Sample code for 30+ languages & platforms
Lazarus Pascal Requires Chilkat v11.7.0+

Encrypt and Sign a PDF, and Sign an Encrypted PDF

See more PDF Protection Examples

Demonstrates signing together with encryption. A pending encrypt is applied by SignPdf before it signs, so one call produces a PDF that is both encrypted and signed. A PDF that is already encrypted can be signed too, and stays encrypted. When it was opened with only the user password its permissions decide: adding a signature field needs both the modify and the annotate permission. Loading the PDF with its owner password lifts that.

Chilkat Lazarus Pascal Downloads

Lazarus Pascal
program ChilkatDemo;

// Demonstrates using the Chilkat Pascal wrapper via the C bridge DLL.
// Builds as a console application under Lazarus (FPC) or Delphi.

{$IFDEF FPC}
  {$MODE DELPHI}
{$ENDIF}
{$APPTYPE CONSOLE}

uses
  {$IFDEF UNIX}
  cthreads,
  {$ENDIF}
  SysUtils,
  CkDllLoader,
  Chilkat.Pdf,
  Chilkat.Cert,
  Chilkat.JsonObject;

// ---------------------------------------------------------------------------

procedure RunDemo;
var
  success: Boolean;
  cert: TCert;
  pdf: TPdf;
  json: TJsonObject;
  jsonOut: TJsonObject;
  sigOpts: TJsonObject;
  check: TPdf;
  empty: TJsonObject;
  info: TJsonObject;
  sigInfo: TJsonObject;
  verified: Boolean;
  owner: TPdf;
  twice: TPdf;

begin
  success := False;

  //  This example requires the Chilkat API to have been previously unlocked.
  //  See Global Unlock Sample for sample code.

  //  The PDF used in this example is available at two_page_memo.pdf

  //  The signing certificate, with its private key.
  cert := TCert.Create;
  success := cert.LoadPfxFile('qa_data/pfx/myPdfSigningCert.pfx','secret');
  if (success = False) then
    begin
      WriteLn(cert.LastErrorText);
      Exit;
    end;

  pdf := TPdf.Create;
  success := pdf.LoadFile('qa_data/pdf/two_page_memo.pdf');
  if (success = False) then
    begin
      WriteLn(pdf.LastErrorText);
      Exit;
    end;

  //  Encrypt with AES-256 and do not permit modifying.
  pdf.UserPassword := 'user-secret';
  pdf.OwnerPassword := 'owner-secret';
  json := TJsonObject.Create;
  json.UpdateBool('permissions.modify',False);
  jsonOut := TJsonObject.Create;
  success := pdf.Protection('encrypt',json,jsonOut);
  if (success = False) then
    begin
      WriteLn(pdf.LastErrorText);
      Exit;
    end;

  //  The encryption is still pending.  SignPdf applies it first and signs the encrypted result.
  success := pdf.SetSigningCert(cert);
  if (success = False) then
    begin
      WriteLn(pdf.LastErrorText);
      Exit;
    end;
  sigOpts := TJsonObject.Create;
  sigOpts.UpdateBool('invisibleSignature',True);
  sigOpts.UpdateInt('signingCertificateV2',1);
  sigOpts.UpdateInt('signingTime',1);
  success := pdf.SignPdf(sigOpts,'qa_output/memo_encrypted_signed.pdf');
  if (success = False) then
    begin
      WriteLn(pdf.LastErrorText);
      Exit;
    end;

  //  The result is encrypted and signed.
  check := TPdf.Create;
  check.UserPassword := 'user-secret';
  success := check.LoadFile('qa_output/memo_encrypted_signed.pdf');
  if (success = False) then
    begin
      WriteLn(check.LastErrorText);
      Exit;
    end;
  empty := TJsonObject.Create;
  info := TJsonObject.Create;
  success := check.Protection('getInfo',empty,info);
  if (success = False) then
    begin
      WriteLn(check.LastErrorText);
      Exit;
    end;
  WriteLn('algorithm: ' + info.StringOf('loaded.algorithm'));
  WriteLn('signatures: ' + check.NumSignatures);
  sigInfo := TJsonObject.Create;
  verified := check.VerifySignature(0,sigInfo);
  WriteLn('signature verifies: ' + verified);

  //  Signing an encrypted PDF.  This one was opened with only the user password, and its
  //  permissions do not allow modifying, so another signature is refused.
  success := check.SetSigningCert(cert);
  if (success = False) then
    begin
      WriteLn(check.LastErrorText);
      Exit;
    end;
  success := check.SignPdf(sigOpts,'qa_output/memo_signed_twice.pdf');
  if (success = False) then
    begin
      WriteLn('A second signature was refused: the permissions do not allow it.');
    end;

  //  Loaded with the owner password, the same PDF can be signed.  It stays encrypted, and the
  //  first signature stays valid because the new one is added as an incremental update.
  owner := TPdf.Create;
  owner.UserPassword := 'user-secret';
  owner.OwnerPassword := 'owner-secret';
  success := owner.LoadFile('qa_output/memo_encrypted_signed.pdf');
  if (success = False) then
    begin
      WriteLn(owner.LastErrorText);
      Exit;
    end;
  success := owner.SetSigningCert(cert);
  if (success = False) then
    begin
      WriteLn(owner.LastErrorText);
      Exit;
    end;
  success := owner.SignPdf(sigOpts,'qa_output/memo_signed_twice.pdf');
  if (success = False) then
    begin
      WriteLn(owner.LastErrorText);
      Exit;
    end;

  twice := TPdf.Create;
  twice.UserPassword := 'user-secret';
  success := twice.LoadFile('qa_output/memo_signed_twice.pdf');
  if (success = False) then
    begin
      WriteLn(twice.LastErrorText);
      Exit;
    end;
  WriteLn('signatures after signing with owner rights: ' + twice.NumSignatures);
  verified := twice.VerifySignature(0,sigInfo);
  WriteLn('first signature still verifies: ' + verified);
  verified := twice.VerifySignature(1,sigInfo);
  WriteLn('second signature verifies: ' + verified);

  //  Sample output:

  //  algorithm: aes-256
  //  signatures: 1
  //  signature verifies: True
  //  A second signature was refused: the permissions do not allow it.
  //  signatures after signing with owner rights: 2
  //  first signature still verifies: True
  //  second signature verifies: True


  cert.Free;
  pdf.Free;
  json.Free;
  jsonOut.Free;
  sigOpts.Free;
  check.Free;
  empty.Free;
  info.Free;
  sigInfo.Free;
  owner.Free;
  twice.Free;

end;

// ---------------------------------------------------------------------------

begin

  try
    RunDemo;
  except
    on E: Exception do
      WriteLn('Unhandled exception: ', E.ClassName, ': ', E.Message);
  end;

  WriteLn;
  {$IFDEF MSWINDOWS}
  WriteLn('Press Enter to exit...');
  ReadLn;
  {$ENDIF}
end.