Sample code for 30+ languages & platforms
Lua Requires Chilkat v11.0.0+

Validate CAdES-T Signature (.p7m)

See more CAdES Examples

Validates a CAdES-T CMS signature and extracts the time-stamp token and gets information about it. Also validates the time-stamp token.

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.

local crypt = chilkat.Crypt2.new()

-- Indicate that the CAdES-T timestamp tokens must also pass validation for the signature to be validated.
local cmsOptions = chilkat.JsonObject.new()
cmsOptions:update_bool("ValidateTimestampTokens", true)
crypt.cms_options = cmsOptions:emit()

-- Validate the .p7m and extract the original signed data to an output file.
-- Note: The timestampToken is an unauthenticated attribute.  See the code below that retrieves and parses the last JSON data.
-- for details about examining timestampToken.
local success = crypt:verify_p7_m("qa_data/cades/CAdES-T/Signature-C-T-1.p7m", "qa_output/out.dat")

-- Get information about the CMS signature in the last JSON data.
-- The detailed results of the signature validation are available in the last JSON data.
-- (If the non-success return status was caused by an error such as "file not found", then the
-- last JSON data would be empty.)
local json = chilkat.JsonObject.new()
crypt:get_last_json_data(json)
json.emit_compact = false
print(json:emit())

-- Here is a sample result:
-- See the parsing code below..

-- Use this online tool to generate parsing code from sample JSON:
-- Generate Parsing Code from JSON

-- {
--   "pkcs7": {
--     "verify": {
--       "digestAlgorithms": [
--         "sha256"
--       ],
--       "signerInfo": [
--         {
--           "cert": {
--             "serialNumber": "00DCB814678CDB",
--             "issuerCN": "LevelBCAOK",
--             "issuerDN": "",
--             "digestAlgOid": "2.16.840.1.101.3.4.2.1",
--             "digestAlgName": "SHA256"
--           },
--           "contentType": "1.2.840.113549.1.7.1",
--           "signingTime": "131203065741Z",
--           "messageDigest": "JJZt41Nt8VsYahP+Xti4rR3vBDkUfRd6gquItl6R5Os=",
--           "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.7.1"
--             },
--             "1.2.840.113549.1.9.5": {
--               "name": "signingTime",
--               "utctime": "131203065741Z"
--             },
--             "1.2.840.113549.1.9.4": {
--               "name": "messageDigest",
--               "digest": "JJZt41Nt8VsYahP+Xti4rR3vBDkUfRd6gquItl6R5Os="
--             },
--             "1.2.840.113549.1.9.16.2.47": {
--               "name": "signingCertificateV2",
--               "der": "MIGIMIGFMIGCBCBJrxOU0w0dWGsVovjLv9QDH3syB5mLVv3grSYA40x9IDBeMFOkUTBPMQswCQYDVQQGEwJGUjENMAsGA1UEChMERVRTSTEcMBoGA1UECwwTUGx1Z3Rlc3RzXzIwMTMtMjAxNDETMBEGA1UEAxMKTGV2ZWxCQ0FPSwIHANy4FGeM2w=="
--             }
--           },
--           "unauthAttr": {
--             "1.2.840.113549.1.9.16.2.14": {
--               "name": "timestampToken",
--               "der": "MIIL+AYJKoZI...u7CfcjURNTY=",
--               "verify": {
--                 "digestAlgorithms": [
--                   "sha256"
--                 ],
--                 "signerInfo": [
--                   {
--                     "cert": {
--                       "serialNumber": "01AA4592D36C61",
--                       "issuerCN": "RootCAOK",
--                       "issuerDN": "",
--                       "digestAlgOid": "2.16.840.1.101.3.4.2.1",
--                       "digestAlgName": "SHA256"
--                     },
--                     "contentType": "1.2.840.113549.1.9.16.1.4",
--                     "messageDigest": "NSsMUrfoyCQ0OszPE1YLx1j3EyyCiBmnE5Sua6ghu/Q=",
--                     "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.4": {
--                         "name": "messageDigest",
--                         "digest": "NSsMUrfoyCQ0OszPE1YLx1j3EyyCiBmnE5Sua6ghu/Q="
--                       },
--                       "1.2.840.113549.1.9.16.2.47": {
--                         "name": "signingCertificateV2",
--                         "der": "MIGGMIGDMIGABCDB/np5UxvhcPnSxD2Kme+C88uXGCMWLAvFPHNvTApTWDBcMFGkTzBNMQswCQYDVQQGEwJGUjENMAsGA1UEChMERVRTSTEcMBoGA1UECwwTUGx1Z3Rlc3RzXzIwMTMtMjAxNDERMA8GA1UEAxMIUm9vdENBT0sCBwGqRZLTbGE="
--                       }
--                     }
--                   }
--                 ]
--               },
--               "timestampSignatureVerified": true,
--               "tstInfo": {
--                 "tsaPolicyId": "1.3.6.1.4.1.2706.2.2.5.2.1.1.1",
--                 "messageImprint": {
--                   "hashAlg": "sha256",
--                   "digest": "C8xEe9NA4X1cUyHGX9zG89ipmQ2byFs3aa+Xe4Fz2P0=",
--                   "digestMatches": true
--                 },
--                 "serialNumber": "313E162121D922",
--                 "genTime": "20131203065742Z"
--               }
--             }
--           }
--         }
--       ]
--     }
--   }
-- }
--

local strVal = ""
local certSerialNumber = ""
local certIssuerCN = ""
local certIssuerDN = ""
local certDigestAlgOid = ""
local certDigestAlgName = ""
local contentType = ""
local signingTime = chilkat.DtObj.new()
local messageDigest = ""
local signingAlgOid = ""
local signingAlgName = ""
local authAttrContentTypeName = ""
local authAttrContentTypeOid = ""
local authAttrSigningTimeName = ""
local authAttrSigningTimeUtctime = chilkat.DtObj.new()
local authAttrMessageDigestName = ""
local authAttrMessageDigestDigest = ""
local authAttrSigningCertificateV2Name = ""
local authAttrSigningCertificateV2Der = ""
local unauthAttrTimestampTokenName = ""
local unauthAttrTimestampTokenDer = ""
local unauthAttrTimestampTokenTimestampSignatureVerified = false
local unauthAttrTimestampTokenTstInfoTsaPolicyId = ""
local unauthAttrTimestampTokenTstInfoMessageImprintHashAlg = ""
local unauthAttrTimestampTokenTstInfoMessageImprintDigest = ""
local unauthAttrTimestampTokenTstInfoMessageImprintDigestMatches = false
local unauthAttrTimestampTokenTstInfoSerialNumber = ""
local unauthAttrTimestampTokenTstInfoGenTime = chilkat.DtObj.new()
local j = 0
local count_j = 0

-- Iterate over the hash algorithms used in the signature.
local i = 0
local 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

-- For each signer...
i = 0
count_i = json:size_of_array("pkcs7.verify.signerInfo")
while i < count_i do
    json.i = i

    -- Get information about the certificate used by this signer.
    certSerialNumber = json:string_of("pkcs7.verify.signerInfo[i].cert.serialNumber")
    certIssuerCN = json:string_of("pkcs7.verify.signerInfo[i].cert.issuerCN")
    certIssuerDN = json:string_of("pkcs7.verify.signerInfo[i].cert.issuerDN")
    certDigestAlgOid = json:string_of("pkcs7.verify.signerInfo[i].cert.digestAlgOid")
    certDigestAlgName = json:string_of("pkcs7.verify.signerInfo[i].cert.digestAlgName")

    -- Get additional information for this signer, such as the signingTime, signature algorithm, etc.
    contentType = json:string_of("pkcs7.verify.signerInfo[i].contentType")
    json:dt_of("pkcs7.verify.signerInfo[i].signingTime", false, signingTime)
    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")

    -- --------------------------------
    -- Examine authenticated attributes.
    -- --------------------------------

    -- contentType
    if json:has_member("pkcs7.verify.signerInfo[i].authAttr.\"1.2.840.113549.1.9.3\"") then
        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")
    end

    -- signingTime
    if json:has_member("pkcs7.verify.signerInfo[i].authAttr.\"1.2.840.113549.1.9.5\"") then
        authAttrSigningTimeName = json:string_of("pkcs7.verify.signerInfo[i].authAttr.\"1.2.840.113549.1.9.5\".name")
        json:dt_of("pkcs7.verify.signerInfo[i].authAttr.\"1.2.840.113549.1.9.5\".utctime", false, authAttrSigningTimeUtctime)
    end

    -- messageDigest
    if json:has_member("pkcs7.verify.signerInfo[i].authAttr.\"1.2.840.113549.1.9.4\"") then
        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")
    end

    -- signingCertificateV2
    if json:has_member("pkcs7.verify.signerInfo[i].authAttr.\"1.2.840.113549.1.9.16.2.47\"") then
        authAttrSigningCertificateV2Name = json:string_of("pkcs7.verify.signerInfo[i].authAttr.\"1.2.840.113549.1.9.16.2.47\".name")
        authAttrSigningCertificateV2Der = json:string_of("pkcs7.verify.signerInfo[i].authAttr.\"1.2.840.113549.1.9.16.2.47\".der")
    end

    -- --------------------------------
    -- Examine unauthenticated attributes.
    -- --------------------------------

    -- timestampToken  (the timestampToken is what makes this signature a CAdES-T)
    if json:has_member("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\"") then
        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")

        -- This is where we find out if the timestampToken's signature is valid.
        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")

        -- Here is where we check to see if the digest in the timestampToken's messageImprint matches the digest of the signature of this signerInfo
        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")

        -- Here is where we get the date/time of the timestampToken (i.e. when it was timestamped)
        json:dt_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".tstInfo.genTime", false, unauthAttrTimestampTokenTstInfoGenTime)

        -- The following code gets details about the validity of the timestampToken's signature...
        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")
            certIssuerDN = json:string_of("pkcs7.verify.signerInfo[i].unauthAttr.\"1.2.840.113549.1.9.16.2.14\".verify.signerInfo[j].cert.issuerDN")
            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")
            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")
            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")
            authAttrSigningCertificateV2Name = 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.47\".name")
            authAttrSigningCertificateV2Der = 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.47\".der")
            j = j + 1
        end
    end

    i = i + 1
end

if not success then
    print(crypt.last_error_text)
    print("CAdES-T verification failed.")
else
    print("CAdES-T signature is valid.")
end