Sample code for 30+ languages & platforms
Lua 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 Lua Downloads

Lua
local chilkat = require("chilkat")

-- 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.
local cert = chilkat.Cert.new()
local success = cert:load_pfx_file("qa_data/pfx/myPdfSigningCert.pfx", "secret")
if not success then
    print(cert.last_error_text)
    return
end

local pdf = chilkat.Pdf.new()
success = pdf:load_file("qa_data/pdf/two_page_memo.pdf")
if not success then
    print(pdf.last_error_text)
    return
end

-- Encrypt with AES-256 and do not permit modifying.
pdf.user_password = "user-secret"
pdf.owner_password = "owner-secret"
local json = chilkat.JsonObject.new()
json:update_bool("permissions.modify", false)
local jsonOut = chilkat.JsonObject.new()
success = pdf:protection("encrypt", json, jsonOut)
if not success then
    print(pdf.last_error_text)
    return
end

-- The encryption is still pending.  SignPdf applies it first and signs the encrypted result.
success = pdf:set_signing_cert(cert)
if not success then
    print(pdf.last_error_text)
    return
end

local sigOpts = chilkat.JsonObject.new()
sigOpts:update_bool("invisibleSignature", true)
sigOpts:update_int("signingCertificateV2", 1)
sigOpts:update_int("signingTime", 1)
success = pdf:sign_pdf(sigOpts, "qa_output/memo_encrypted_signed.pdf")
if not success then
    print(pdf.last_error_text)
    return
end

-- The result is encrypted and signed.
local check = chilkat.Pdf.new()
check.user_password = "user-secret"
success = check:load_file("qa_output/memo_encrypted_signed.pdf")
if not success then
    print(check.last_error_text)
    return
end

local empty = chilkat.JsonObject.new()
local info = chilkat.JsonObject.new()
success = check:protection("getInfo", empty, info)
if not success then
    print(check.last_error_text)
    return
end

print("algorithm: " .. info:string_of("loaded.algorithm"))
print("signatures: " .. check.num_signatures)
local sigInfo = chilkat.JsonObject.new()
local verified = check:verify_signature(0, sigInfo)
print("signature verifies: " .. tostring(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:set_signing_cert(cert)
if not success then
    print(check.last_error_text)
    return
end

success = check:sign_pdf(sigOpts, "qa_output/memo_signed_twice.pdf")
if not success then
    print("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.
local owner = chilkat.Pdf.new()
owner.user_password = "user-secret"
owner.owner_password = "owner-secret"
success = owner:load_file("qa_output/memo_encrypted_signed.pdf")
if not success then
    print(owner.last_error_text)
    return
end

success = owner:set_signing_cert(cert)
if not success then
    print(owner.last_error_text)
    return
end

success = owner:sign_pdf(sigOpts, "qa_output/memo_signed_twice.pdf")
if not success then
    print(owner.last_error_text)
    return
end

local twice = chilkat.Pdf.new()
twice.user_password = "user-secret"
success = twice:load_file("qa_output/memo_signed_twice.pdf")
if not success then
    print(twice.last_error_text)
    return
end

print("signatures after signing with owner rights: " .. twice.num_signatures)
verified = twice:verify_signature(0, sigInfo)
print("first signature still verifies: " .. tostring(verified))
verified = twice:verify_signature(1, sigInfo)
print("second signature verifies: " .. tostring(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