PureBasic
PureBasic
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.Note: This example requires Chilkat v9.5.0.85 or greater.
Chilkat PureBasic Downloads
IncludeFile "CkDtObj.pb"
IncludeFile "CkJsonObject.pb"
IncludeFile "CkPdf.pb"
Procedure ChilkatExample()
success.i = 0
; This example requires the Chilkat API to have been previously unlocked.
; See Global Unlock Sample for sample code.
pdf.i = CkPdf::ckCreate()
If pdf.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
; Load a PDF that has cryptographic signatures to be validated
success = CkPdf::ckLoadFile(pdf,"qa_data/pdf/sign_testing_1/helloSigned2.pdf")
If success = 0
Debug CkPdf::ckLastErrorText(pdf)
CkPdf::ckDispose(pdf)
ProcedureReturn
EndIf
; Each time we verify a signature, information about the signature is written into
; sigInfo (replacing whatever sigInfo previously contained).
sigInfo.i = CkJsonObject::ckCreate()
If sigInfo.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
CkJsonObject::setCkEmitCompact(sigInfo, 0)
; Iterate over each signature and validate each.
numSignatures.i = CkPdf::ckNumSignatures(pdf)
validated.i = 0
i.i = 0
While i < numSignatures
validated = CkPdf::ckVerifySignature(pdf,i,sigInfo)
Debug "Signature " + Str(i) + " validated: " + Str(validated)
Debug CkJsonObject::ckEmit(sigInfo)
i = i + 1
Wend
Debug "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.
json.i = CkJsonObject::ckCreate()
If json.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
; 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
unauthAttrTimestampTokenTstInfoGenTime.i = CkDtObj::ckCreate()
If unauthAttrTimestampTokenTstInfoGenTime.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
signingTime.i = CkDtObj::ckCreate()
If signingTime.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
authAttrSigningTimeUtctime.i = CkDtObj::ckCreate()
If authAttrSigningTimeUtctime.i = 0
Debug "Failed to create object."
ProcedureReturn
EndIf
intVal.i
strVal.s
issuerCN.s
serial.s
certSerialNumber.s
certIssuerCN.s
certDigestAlgOid.s
certDigestAlgName.s
contentType.s
messageDigest.s
signingAlgOid.s
signingAlgName.s
authAttr1_2_840_113583_1_1_8Der.s
authAttrContentTypeName.s
authAttrContentTypeOid.s
authAttrMessageDigestName.s
authAttrMessageDigestDigest.s
unauthAttrTimestampTokenName.s
unauthAttrTimestampTokenDer.s
unauthAttrTimestampTokenTimestampSignatureVerified.i
unauthAttrTimestampTokenTstInfoTsaPolicyId.s
unauthAttrTimestampTokenTstInfoMessageImprintHashAlg.s
unauthAttrTimestampTokenTstInfoMessageImprintDigest.s
unauthAttrTimestampTokenTstInfoMessageImprintDigestMatches.i
unauthAttrTimestampTokenTstInfoSerialNumber.s
j.i
count_j.i
authAttrSigningTimeName.s
authAttrSigningCertificateName.s
authAttrSigningCertificateDer.s
validated = CkJsonObject::ckBoolOf(json,"validated")
signatureDictionary_Contents.s = CkJsonObject::ckStringOf(json,"signatureDictionary./Contents")
signatureDictionary_Filter.s = CkJsonObject::ckStringOf(json,"signatureDictionary./Filter")
signatureDictionary_M.s = CkJsonObject::ckStringOf(json,"signatureDictionary./M")
signatureDictionary_Name.s = CkJsonObject::ckStringOf(json,"signatureDictionary./Name")
signatureDictionary_Prop_Build_App_Name.s = CkJsonObject::ckStringOf(json,"signatureDictionary./Prop_Build./App./Name")
signatureDictionary_Prop_Build_App_R.i = CkJsonObject::ckIntOf(json,"signatureDictionary./Prop_Build./App./R")
signatureDictionary_Prop_Build_App_REx.s = CkJsonObject::ckStringOf(json,"signatureDictionary./Prop_Build./App./REx")
signatureDictionary_Prop_Build_App_TrustedMode.i = CkJsonObject::ckBoolOf(json,"signatureDictionary./Prop_Build./App./TrustedMode")
signatureDictionary_Prop_Build_Filter_Date.s = CkJsonObject::ckStringOf(json,"signatureDictionary./Prop_Build./Filter./Date")
signatureDictionary_Prop_Build_Filter_Name.s = CkJsonObject::ckStringOf(json,"signatureDictionary./Prop_Build./Filter./Name")
signatureDictionary_Prop_Build_Filter_R.i = CkJsonObject::ckIntOf(json,"signatureDictionary./Prop_Build./Filter./R")
signatureDictionary_Prop_Build_Filter_V.i = CkJsonObject::ckIntOf(json,"signatureDictionary./Prop_Build./Filter./V")
signatureDictionary_Prop_Build_PubSec_Date.s = CkJsonObject::ckStringOf(json,"signatureDictionary./Prop_Build./PubSec./Date")
signatureDictionary_Prop_Build_PubSec_NonEFontNoWarn.i = CkJsonObject::ckBoolOf(json,"signatureDictionary./Prop_Build./PubSec./NonEFontNoWarn")
signatureDictionary_Prop_Build_PubSec_R.i = CkJsonObject::ckIntOf(json,"signatureDictionary./Prop_Build./PubSec./R")
signatureDictionary_SubFilter.s = CkJsonObject::ckStringOf(json,"signatureDictionary./SubFilter")
signatureDictionary_Type.s = CkJsonObject::ckStringOf(json,"signatureDictionary./Type")
i = 0
count_i.i = CkJsonObject::ckSizeOfArray(json,"signatureDictionary./ByteRange")
While i < count_i
CkJsonObject::setCkI(json, i)
intVal = CkJsonObject::ckIntOf(json,"signatureDictionary./ByteRange[i]")
i = i + 1
Wend
i = 0
count_i = CkJsonObject::ckSizeOfArray(json,"signatureDictionary./Prop_Build./App./OS")
While i < count_i
CkJsonObject::setCkI(json, i)
strVal = CkJsonObject::ckStringOf(json,"signatureDictionary./Prop_Build./App./OS[i]")
i = i + 1
Wend
i = 0
count_i = CkJsonObject::ckSizeOfArray(json,"pkcs7.verify.certs")
While i < count_i
CkJsonObject::setCkI(json, i)
issuerCN = CkJsonObject::ckStringOf(json,"pkcs7.verify.certs[i].issuerCN")
serial = CkJsonObject::ckStringOf(json,"pkcs7.verify.certs[i].serial")
i = i + 1
Wend
i = 0
count_i = CkJsonObject::ckSizeOfArray(json,"pkcs7.verify.digestAlgorithms")
While i < count_i
CkJsonObject::setCkI(json, i)
strVal = CkJsonObject::ckStringOf(json,"pkcs7.verify.digestAlgorithms[i]")
i = i + 1
Wend
i = 0
count_i = CkJsonObject::ckSizeOfArray(json,"pkcs7.verify.signerInfo")
While i < count_i
CkJsonObject::setCkI(json, i)
certSerialNumber = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].cert.serialNumber")
certIssuerCN = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].cert.issuerCN")
certDigestAlgOid = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].cert.digestAlgOid")
certDigestAlgName = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].cert.digestAlgName")
contentType = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].contentType")
messageDigest = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].messageDigest")
signingAlgOid = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].signingAlgOid")
signingAlgName = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].signingAlgName")
authAttr1_2_840_113583_1_1_8Der = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].authAttr." + Chr(34) + "1.2.840.113583.1.1.8" + Chr(34) + ".der")
authAttrContentTypeName = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].authAttr." + Chr(34) + "1.2.840.113549.1.9.3" + Chr(34) + ".name")
authAttrContentTypeOid = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].authAttr." + Chr(34) + "1.2.840.113549.1.9.3" + Chr(34) + ".oid")
authAttrMessageDigestName = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].authAttr." + Chr(34) + "1.2.840.113549.1.9.4" + Chr(34) + ".name")
authAttrMessageDigestDigest = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].authAttr." + Chr(34) + "1.2.840.113549.1.9.4" + Chr(34) + ".digest")
unauthAttrTimestampTokenName = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".name")
unauthAttrTimestampTokenDer = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".der")
unauthAttrTimestampTokenTimestampSignatureVerified = CkJsonObject::ckBoolOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".timestampSignatureVerified")
unauthAttrTimestampTokenTstInfoTsaPolicyId = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".tstInfo.tsaPolicyId")
unauthAttrTimestampTokenTstInfoMessageImprintHashAlg = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".tstInfo.messageImprint.hashAlg")
unauthAttrTimestampTokenTstInfoMessageImprintDigest = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".tstInfo.messageImprint.digest")
unauthAttrTimestampTokenTstInfoMessageImprintDigestMatches = CkJsonObject::ckBoolOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".tstInfo.messageImprint.digestMatches")
unauthAttrTimestampTokenTstInfoSerialNumber = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".tstInfo.serialNumber")
CkJsonObject::ckDtOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".tstInfo.genTime",0,unauthAttrTimestampTokenTstInfoGenTime)
j = 0
count_j = CkJsonObject::ckSizeOfArray(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.digestAlgorithms")
While j < count_j
CkJsonObject::setCkJ(json, j)
strVal = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.digestAlgorithms[j]")
j = j + 1
Wend
j = 0
count_j = CkJsonObject::ckSizeOfArray(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo")
While j < count_j
CkJsonObject::setCkJ(json, j)
certSerialNumber = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].cert.serialNumber")
certIssuerCN = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].cert.issuerCN")
certDigestAlgOid = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].cert.digestAlgOid")
certDigestAlgName = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].cert.digestAlgName")
contentType = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].contentType")
CkJsonObject::ckDtOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].signingTime",0,signingTime)
messageDigest = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].messageDigest")
signingAlgOid = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].signingAlgOid")
signingAlgName = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].signingAlgName")
authAttrContentTypeName = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].authAttr." + Chr(34) + "1.2.840.113549.1.9.3" + Chr(34) + ".name")
authAttrContentTypeOid = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].authAttr." + Chr(34) + "1.2.840.113549.1.9.3" + Chr(34) + ".oid")
authAttrSigningTimeName = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].authAttr." + Chr(34) + "1.2.840.113549.1.9.5" + Chr(34) + ".name")
CkJsonObject::ckDtOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].authAttr." + Chr(34) + "1.2.840.113549.1.9.5" + Chr(34) + ".utctime",0,authAttrSigningTimeUtctime)
authAttrSigningCertificateName = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].authAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.12" + Chr(34) + ".name")
authAttrSigningCertificateDer = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].authAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.12" + Chr(34) + ".der")
authAttrMessageDigestName = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].authAttr." + Chr(34) + "1.2.840.113549.1.9.4" + Chr(34) + ".name")
authAttrMessageDigestDigest = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34) + ".verify.signerInfo[j].authAttr." + Chr(34) + "1.2.840.113549.1.9.4" + Chr(34) + ".digest")
j = j + 1
Wend
i = i + 1
Wend
i = 0
count_i = CkJsonObject::ckSizeOfArray(json,"pkcs7.verify.pkcs7.verify.certs")
While i < count_i
CkJsonObject::setCkI(json, i)
issuerCN = CkJsonObject::ckStringOf(json,"pkcs7.verify.pkcs7.verify.certs[i].issuerCN")
serial = CkJsonObject::ckStringOf(json,"pkcs7.verify.pkcs7.verify.certs[i].serial")
i = i + 1
Wend
CkPdf::ckDispose(pdf)
CkJsonObject::ckDispose(sigInfo)
CkJsonObject::ckDispose(json)
CkDtObj::ckDispose(unauthAttrTimestampTokenTstInfoGenTime)
CkDtObj::ckDispose(signingTime)
CkDtObj::ckDispose(authAttrSigningTimeUtctime)
ProcedureReturn
EndProcedure