Lua Requires Chilkat v9.5.0.85+
Lua
Validate PDF Signatures
See more PDF Signatures Examples
This example demonstrates how to validate the signatures in a PDF and also shows how to get information from each signature.Chilkat Lua Downloads
local chilkat = require("chilkat")
-- This example requires the Chilkat API to have been previously unlocked.
-- See Global Unlock Sample for sample code.
local pdf = chilkat.Pdf.new()
-- Load a PDF that has cryptographic signatures to be validated
local success = pdf:load_file("qa_data/pdf/sign_testing_1/helloSigned2.pdf")
if not success then
print(pdf.last_error_text)
return
end
-- Each time we verify a signature, information about the signature is written into
-- sigInfo (replacing whatever sigInfo previously contained).
local sigInfo = chilkat.JsonObject.new()
sigInfo.emit_compact = false
-- Iterate over each signature and validate each.
local numSignatures = pdf.num_signatures
local validated = false
local i = 0
while i < numSignatures do
validated = pdf:verify_signature(i, sigInfo)
print("Signature " .. i .. " validated: " .. tostring(validated))
print(sigInfo:emit())
i = i + 1
end
print("Finished.")
-- When VerifySignature validates a signature, a lot of information is deposited into the JSON sigInfo object.
-- The information can vary depending on what was included in the signature (for example, various authenticated attributes
-- and unauthenticated attributes may or may not be included).
-- Here is a sample of the information you'll see.
--
-- The following online tool can be used to generate code to parse any given JSON.
-- Generate Parsing Code from JSON
-- {
-- "validated": true,
-- "signatureDictionary": { <--- This is the contents of the PDF Signature Dictionary for this signature.
-- "/ByteRange": [
-- 0,
-- 154682,
-- 170512,
-- 3233
-- ],
-- "/Contents": "<hex_data>",
-- "/Filter": "/Adobe.PPKLite", <--- The meaning of the Signature Dictionary entries are defined in the PDF format specification document.
-- "/M": "D:20201006110216-05'00'",
-- "/Name": "yubikey rsa 1024 authentication",
-- "/Prop_Build": {
-- "/App": {
-- "/Name": "/Adobe#20Acrobat#20Pro#20DC",
-- "/OS": [
-- "/Win"
-- ],
-- "/R": 1313792,
-- "/REx": "2020.012.20048",
-- "/TrustedMode": true
-- },
-- "/Filter": {
-- "/Date": "Sep 11 2020 16:30:54",
-- "/Name": "/Adobe.PPKLite",
-- "/R": 131104,
-- "/V": 2
-- },
-- "/PubSec": {
-- "/Date": "Sep 11 2020 16:30:54",
-- "/NonEFontNoWarn": true,
-- "/R": 131105
-- }
-- },
-- "/SubFilter": "/adbe.pkcs7.detached",
-- "/Type": "/Sig"
-- },
-- "pkcs7": { <--- This is the content of the CMS signature.
-- "verify": {
-- "certs": [ <--- Each signing certificate is listed here (by issuer common name and signing cert's serail number (in hex))
-- {
-- "issuerCN": "yubikey rsa 1024 authentication",
-- "serial": "66BE58138D761E92BC594A722932657BE26D421F"
-- }
-- ],
-- "digestAlgorithms": [
-- "sha256"
-- ],
-- "signerInfo": [ <--- contains data from each SignerInfo
-- {
-- "cert": {
-- "serialNumber": "66BE58138D761E92BC594A722932657BE26D421F",
-- "issuerCN": "yubikey rsa 1024 authentication",
-- "digestAlgOid": "2.16.840.1.101.3.4.2.1",
-- "digestAlgName": "SHA256"
-- },
-- "contentType": "1.2.840.113549.1.7.1",
-- "messageDigest": "btQOuSEvC31mdRFHtyEUPw8R9NuKfk0XPcQ6Lcmn6pk=",
-- "signingAlgOid": "1.2.840.113549.1.1.11",
-- "signingAlgName": "RSA-SHA256-PKCSV-1_5",
-- "authAttr": { <--- CMS authenticated attributes are contained here.
-- "1.2.840.113583.1.1.8": {
-- "der": "MAA="
-- },
-- "1.2.840.113549.1.9.3": {
-- "name": "contentType",
-- "oid": "1.2.840.113549.1.7.1"
-- },
-- "1.2.840.113549.1.9.4": {
-- "name": "messageDigest",
-- "digest": "btQOuSEvC31mdRFHtyEUPw8R9NuKfk0XPcQ6Lcmn6pk="
-- }
-- },
-- "unauthAttr": { <--- CMS unauthenticated attributes are contained here.
-- "1.2.840.113549.1.9.16.2.14": {
-- "name": "timestampToken",
-- "der": "MIIOvAYJKo ... Es/70g=",
-- "verify": {
-- "digestAlgorithms": [
-- "sha256"
-- ],
-- "signerInfo": [
-- {
-- "cert": {
-- "serialNumber": "04CD3F8568AE76C61BB0FE7160CCA76D",
-- "issuerCN": "DigiCert SHA2 Assured ID Timestamping CA",
-- "digestAlgOid": "2.16.840.1.101.3.4.2.1",
-- "digestAlgName": "SHA256"
-- },
-- "contentType": "1.2.840.113549.1.9.16.1.4",
-- "signingTime": "201006160423Z",
-- "messageDigest": "Atv5Rj3kidB8IR6CplYiX3o6De/k8SC6JJ6uUPAGO0g=",
-- "signingAlgOid": "1.2.840.113549.1.1.1",
-- "signingAlgName": "RSA-PKCSV-1_5",
-- "authAttr": {
-- "1.2.840.113549.1.9.3": {
-- "name": "contentType",
-- "oid": "1.2.840.113549.1.9.16.1.4"
-- },
-- "1.2.840.113549.1.9.5": {
-- "name": "signingTime",
-- "utctime": "201006160423Z"
-- },
-- "1.2.840.113549.1.9.16.2.12": {
-- "name": "signingCertificate",
-- "der": "MBowGDAWBBQDJb1QXtqWMC3CL0+gHkwovig0xQ=="
-- },
-- "1.2.840.113549.1.9.4": {
-- "name": "messageDigest",
-- "digest": "Atv5Rj3kidB8IR6CplYiX3o6De/k8SC6JJ6uUPAGO0g="
-- }
-- }
-- }
-- ]
-- },
-- "timestampSignatureVerified": true,
-- "tstInfo": {
-- "tsaPolicyId": "2.16.840.1.114412.7.1",
-- "messageImprint": {
-- "hashAlg": "sha256",
-- "digest": "gLJtrRWUSDfjzDkF1MfWG1wyHA6FrUJLkWMGRG+eMlA=",
-- "digestMatches": true
-- },
-- "serialNumber": "00CE57E1113970607EF63B1D1160545321",
-- "genTime": "20201006160423Z"
-- }
-- }
-- }
-- }
-- ],
-- "pkcs7": {
-- "verify": {
-- "certs": [
-- {
-- "issuerCN": "DigiCert SHA2 Assured ID Timestamping CA",
-- "serial": "04CD3F8568AE76C61BB0FE7160CCA76D"
-- },
-- {
-- "issuerCN": "DigiCert Assured ID Root CA",
-- "serial": "0AA125D6D6321B7E41E405DA3697C215"
-- }
-- ]
-- }
-- }
-- }
-- }
-- }
-- **** The point of this code is to show how to get at each desired piece of information contained in the signature.
-- **** If your signature contains additional information not shown here, then you can use the online tool to generate the parse code.
-- **** It is likely you're only interested in a few items of information, and therefore you wouldn't copy all of this code, but might
-- **** choose to use bits and pieces to get the information you find important.
local json = chilkat.JsonObject.new()
-- Imagine that the "json" object contains the information obtained by validating a signature...
-- The code below was generated using the online tool: Generate Parsing Code from JSON
local unauthAttrTimestampTokenTstInfoGenTime = chilkat.DtObj.new()
local signingTime = chilkat.DtObj.new()
local authAttrSigningTimeUtctime = chilkat.DtObj.new()
local intVal = 0
local strVal = ""
local issuerCN = ""
local serial = ""
local certSerialNumber = ""
local certIssuerCN = ""
local certDigestAlgOid = ""
local certDigestAlgName = ""
local contentType = ""
local messageDigest = ""
local signingAlgOid = ""
local signingAlgName = ""
local authAttr1_2_840_113583_1_1_8Der = ""
local authAttrContentTypeName = ""
local authAttrContentTypeOid = ""
local authAttrMessageDigestName = ""
local authAttrMessageDigestDigest = ""
local unauthAttrTimestampTokenName = ""
local unauthAttrTimestampTokenDer = ""
local unauthAttrTimestampTokenTimestampSignatureVerified = false
local unauthAttrTimestampTokenTstInfoTsaPolicyId = ""
local unauthAttrTimestampTokenTstInfoMessageImprintHashAlg = ""
local unauthAttrTimestampTokenTstInfoMessageImprintDigest = ""
local unauthAttrTimestampTokenTstInfoMessageImprintDigestMatches = false
local unauthAttrTimestampTokenTstInfoSerialNumber = ""
local j = 0
local count_j = 0
local authAttrSigningTimeName = ""
local authAttrSigningCertificateName = ""
local authAttrSigningCertificateDer = ""
validated = json:bool_of("validated")
local signatureDictionary_Contents = json:string_of("signatureDictionary./Contents")
local signatureDictionary_Filter = json:string_of("signatureDictionary./Filter")
local signatureDictionary_M = json:string_of("signatureDictionary./M")
local signatureDictionary_Name = json:string_of("signatureDictionary./Name")
local signatureDictionary_Prop_Build_App_Name = json:string_of("signatureDictionary./Prop_Build./App./Name")
local signatureDictionary_Prop_Build_App_R = json:int_of("signatureDictionary./Prop_Build./App./R")
local signatureDictionary_Prop_Build_App_REx = json:string_of("signatureDictionary./Prop_Build./App./REx")
local signatureDictionary_Prop_Build_App_TrustedMode = json:bool_of("signatureDictionary./Prop_Build./App./TrustedMode")
local signatureDictionary_Prop_Build_Filter_Date = json:string_of("signatureDictionary./Prop_Build./Filter./Date")
local signatureDictionary_Prop_Build_Filter_Name = json:string_of("signatureDictionary./Prop_Build./Filter./Name")
local signatureDictionary_Prop_Build_Filter_R = json:int_of("signatureDictionary./Prop_Build./Filter./R")
local signatureDictionary_Prop_Build_Filter_V = json:int_of("signatureDictionary./Prop_Build./Filter./V")
local signatureDictionary_Prop_Build_PubSec_Date = json:string_of("signatureDictionary./Prop_Build./PubSec./Date")
local signatureDictionary_Prop_Build_PubSec_NonEFontNoWarn = json:bool_of("signatureDictionary./Prop_Build./PubSec./NonEFontNoWarn")
local signatureDictionary_Prop_Build_PubSec_R = json:int_of("signatureDictionary./Prop_Build./PubSec./R")
local signatureDictionary_SubFilter = json:string_of("signatureDictionary./SubFilter")
local signatureDictionary_Type = json:string_of("signatureDictionary./Type")
i = 0
local count_i = json:size_of_array("signatureDictionary./ByteRange")
while i < count_i do
json.i = i
intVal = json:int_of("signatureDictionary./ByteRange[i]")
i = i + 1
end
i = 0
count_i = json:size_of_array("signatureDictionary./Prop_Build./App./OS")
while i < count_i do
json.i = i
strVal = json:string_of("signatureDictionary./Prop_Build./App./OS[i]")
i = i + 1
end
i = 0
count_i = json:size_of_array("pkcs7.verify.certs")
while i < count_i do
json.i = i
issuerCN = json:string_of("pkcs7.verify.certs[i].issuerCN")
serial = json:string_of("pkcs7.verify.certs[i].serial")
i = i + 1
end
i = 0
count_i = json:size_of_array("pkcs7.verify.digestAlgorithms")
while i < count_i do
json.i = i
strVal = json:string_of("pkcs7.verify.digestAlgorithms[i]")
i = i + 1
end
i = 0
count_i = json:size_of_array("pkcs7.verify.signerInfo")
while i < count_i do
json.i = i
certSerialNumber = json:string_of("pkcs7.verify.signerInfo[i].cert.serialNumber")
certIssuerCN = json:string_of("pkcs7.verify.signerInfo[i].cert.issuerCN")
certDigestAlgOid = json:string_of("pkcs7.verify.signerInfo[i].cert.digestAlgOid")
certDigestAlgName = json:string_of("pkcs7.verify.signerInfo[i].cert.digestAlgName")
contentType = json:string_of("pkcs7.verify.signerInfo[i].contentType")
messageDigest = json:string_of("pkcs7.verify.signerInfo[i].messageDigest")
signingAlgOid = json:string_of("pkcs7.verify.signerInfo[i].signingAlgOid")
signingAlgName = json:string_of("pkcs7.verify.signerInfo[i].signingAlgName")
authAttr1_2_840_113583_1_1_8Der = json:string_of("pkcs7.verify.signerInfo[i].authAttr.\"1.2.840.113583.1.1.8\".der")
authAttrContentTypeName = json:string_of("pkcs7.verify.signerInfo[i].authAttr.\"1.2.840.113549.1.9.3\".name")
authAttrContentTypeOid = json:string_of("pkcs7.verify.signerInfo[i].authAttr.\"1.2.840.113549.1.9.3\".oid")
authAttrMessageDigestName = json:string_of("pkcs7.verify.signerInfo[i].authAttr.\"1.2.840.113549.1.9.4\".name")
authAttrMessageDigestDigest = json:string_of("pkcs7.verify.signerInfo[i].authAttr.\"1.2.840.113549.1.9.4\".digest")
unauthAttrTimestampTokenName = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".name")
unauthAttrTimestampTokenDer = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".der")
unauthAttrTimestampTokenTimestampSignatureVerified = json:bool_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".timestampSignatureVerified")
unauthAttrTimestampTokenTstInfoTsaPolicyId = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".tstInfo.tsaPolicyId")
unauthAttrTimestampTokenTstInfoMessageImprintHashAlg = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".tstInfo.messageImprint.hashAlg")
unauthAttrTimestampTokenTstInfoMessageImprintDigest = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".tstInfo.messageImprint.digest")
unauthAttrTimestampTokenTstInfoMessageImprintDigestMatches = json:bool_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".tstInfo.messageImprint.digestMatches")
unauthAttrTimestampTokenTstInfoSerialNumber = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".tstInfo.serialNumber")
json:dt_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".tstInfo.genTime", false, unauthAttrTimestampTokenTstInfoGenTime)
j = 0
count_j = json:size_of_array("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.digestAlgorithms")
while j < count_j do
json.j = j
strVal = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.digestAlgorithms[j]")
j = j + 1
end
j = 0
count_j = json:size_of_array("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo")
while j < count_j do
json.j = j
certSerialNumber = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].cert.serialNumber")
certIssuerCN = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].cert.issuerCN")
certDigestAlgOid = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].cert.digestAlgOid")
certDigestAlgName = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].cert.digestAlgName")
contentType = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].contentType")
json:dt_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].signingTime", false, signingTime)
messageDigest = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].messageDigest")
signingAlgOid = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].signingAlgOid")
signingAlgName = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].signingAlgName")
authAttrContentTypeName = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].authAttr.\"1.2.840.113549.1.9.3\".name")
authAttrContentTypeOid = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].authAttr.\"1.2.840.113549.1.9.3\".oid")
authAttrSigningTimeName = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].authAttr.\"1.2.840.113549.1.9.5\".name")
json:dt_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].authAttr.\"1.2.840.113549.1.9.5\".utctime", false, authAttrSigningTimeUtctime)
authAttrSigningCertificateName = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].authAttr.\"1.2.840.113549.1.9.16.2.12\".name")
authAttrSigningCertificateDer = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].authAttr.\"1.2.840.113549.1.9.16.2.12\".der")
authAttrMessageDigestName = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].authAttr.\"1.2.840.113549.1.9.4\".name")
authAttrMessageDigestDigest = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].authAttr.\"1.2.840.113549.1.9.4\".digest")
j = j + 1
end
i = i + 1
end
i = 0
count_i = json:size_of_array("pkcs7.verify.pkcs7.verify.certs")
while i < count_i do
json.i = i
issuerCN = json:string_of("pkcs7.verify.pkcs7.verify.certs[i].issuerCN")
serial = json:string_of("pkcs7.verify.pkcs7.verify.certs[i].serial")
i = i + 1
end