Chilkat HOME .NET Core C# Android™ AutoIt C C# C++ Chilkat2-Python CkPython Classic ASP DataFlex Delphi ActiveX Delphi DLL Go Java Lianja Mono C# Node.js Objective-C PHP ActiveX PHP Extension Perl PowerBuilder PowerShell PureBasic Ruby SQL Server Swift 2 Swift 3,4,5... Tcl Unicode C Unicode C++ VB.NET VBScript Visual Basic 6.0 Visual FoxPro Xojo Plugin
(PureBasic) Validate CAdES-T Signature (.p7m)Validates a CAdES-T CMS signature and extracts the time-stamp token and gets information about it. Also validates the time-stamp token. Note: This example requires Chilkat v9.5.0.78 or greater.
IncludeFile "CkDtObj.pb" IncludeFile "CkJsonObject.pb" IncludeFile "CkCrypt2.pb" Procedure ChilkatExample() ; This example requires the Chilkat API to have been previously unlocked. ; See Global Unlock Sample for sample code. crypt.i = CkCrypt2::ckCreate() If crypt.i = 0 Debug "Failed to create object." ProcedureReturn EndIf success.i ; Indicate that the CAdES-T timestamp tokens must also pass validation for the signature to be validated. cmsOptions.i = CkJsonObject::ckCreate() If cmsOptions.i = 0 Debug "Failed to create object." ProcedureReturn EndIf CkJsonObject::ckUpdateBool(cmsOptions,"ValidateTimestampTokens",1) CkCrypt2::setCkCmsOptions(crypt, CkJsonObject::ckEmit(cmsOptions)) ; 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 parses the LastJsonData ; for details about examining timestampToken. success = CkCrypt2::ckVerifyP7M(crypt,"qa_data/cades/CAdES-T/Signature-C-T-1.p7m","qa_output/out.dat") ; Get information about the CMS signature in the LastJsonData. ; The detailed results of the signature validation are available in LastJsonData. ; (If the non-success return status was caused by an error such as "file not found", then the ; LastJsonData would be empty.) json.i = CkCrypt2::ckLastJsonData(crypt) CkJsonObject::setCkEmitCompact(json, 0) Debug CkJsonObject::ckEmit(json) ; 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" ; } ; } ; } ; } ; ] ; } ; } ; } ; i.i count_i.i strVal.s certSerialNumber.s certIssuerCN.s certIssuerDN.s certDigestAlgOid.s certDigestAlgName.s contentType.s signingTime.i = CkDtObj::ckCreate() If signingTime.i = 0 Debug "Failed to create object." ProcedureReturn EndIf messageDigest.s signingAlgOid.s signingAlgName.s authAttrContentTypeName.s authAttrContentTypeOid.s authAttrSigningTimeName.s authAttrSigningTimeUtctime.i = CkDtObj::ckCreate() If authAttrSigningTimeUtctime.i = 0 Debug "Failed to create object." ProcedureReturn EndIf authAttrMessageDigestName.s authAttrMessageDigestDigest.s authAttrSigningCertificateV2Name.s authAttrSigningCertificateV2Der.s unauthAttrTimestampTokenName.s unauthAttrTimestampTokenDer.s unauthAttrTimestampTokenTimestampSignatureVerified.i unauthAttrTimestampTokenTstInfoTsaPolicyId.s unauthAttrTimestampTokenTstInfoMessageImprintHashAlg.s unauthAttrTimestampTokenTstInfoMessageImprintDigest.s unauthAttrTimestampTokenTstInfoMessageImprintDigestMatches.i unauthAttrTimestampTokenTstInfoSerialNumber.s unauthAttrTimestampTokenTstInfoGenTime.i = CkDtObj::ckCreate() If unauthAttrTimestampTokenTstInfoGenTime.i = 0 Debug "Failed to create object." ProcedureReturn EndIf j.i count_j.i ; Iterate over the hash algorithms used in the signature. 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 ; For each signer... i = 0 count_i = CkJsonObject::ckSizeOfArray(json,"pkcs7.verify.signerInfo") While i < count_i CkJsonObject::setCkI(json, i) ; Get information about the certificate used by this signer. certSerialNumber = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].cert.serialNumber") certIssuerCN = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].cert.issuerCN") certIssuerDN = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].cert.issuerDN") certDigestAlgOid = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].cert.digestAlgOid") certDigestAlgName = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].cert.digestAlgName") ; Get additional information for this signer, such as the signingTime, signature algorithm, etc. contentType = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].contentType") CkJsonObject::ckDtOf(json,"pkcs7.verify.signerInfo[i].signingTime",0,signingTime) 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") ; -------------------------------- ; Examine authenticated attributes. ; -------------------------------- ; contentType If CkJsonObject::ckHasMember(json,"pkcs7.verify.signerInfo[i].authAttr." + Chr(34) + "1.2.840.113549.1.9.3" + Chr(34)) = 1 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") EndIf ; signingTime If CkJsonObject::ckHasMember(json,"pkcs7.verify.signerInfo[i].authAttr." + Chr(34) + "1.2.840.113549.1.9.5" + Chr(34)) = 1 authAttrSigningTimeName = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].authAttr." + Chr(34) + "1.2.840.113549.1.9.5" + Chr(34) + ".name") CkJsonObject::ckDtOf(json,"pkcs7.verify.signerInfo[i].authAttr." + Chr(34) + "1.2.840.113549.1.9.5" + Chr(34) + ".utctime",0,authAttrSigningTimeUtctime) EndIf ; messageDigest If CkJsonObject::ckHasMember(json,"pkcs7.verify.signerInfo[i].authAttr." + Chr(34) + "1.2.840.113549.1.9.4" + Chr(34)) = 1 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") EndIf ; signingCertificateV2 If CkJsonObject::ckHasMember(json,"pkcs7.verify.signerInfo[i].authAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.47" + Chr(34)) = 1 authAttrSigningCertificateV2Name = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].authAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.47" + Chr(34) + ".name") authAttrSigningCertificateV2Der = CkJsonObject::ckStringOf(json,"pkcs7.verify.signerInfo[i].authAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.47" + Chr(34) + ".der") EndIf ; -------------------------------- ; Examine unauthenticated attributes. ; -------------------------------- ; timestampToken (the timestampToken is what makes this signature a CAdES-T) If CkJsonObject::ckHasMember(json,"pkcs7.verify.signerInfo[i].unauthAttr." + Chr(34) + "1.2.840.113549.1.9.16.2.14" + Chr(34)) = 1 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") ; This is where we find out if the timestampToken's signature is valid. 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") ; 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 = 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") ; Here is where we get the date/time of the timestampToken (i.e. when it was timestamped) 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) ; The following code gets details about the validity of the timestampToken's signature... 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") certIssuerDN = 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.issuerDN") 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") 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") 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") authAttrSigningCertificateV2Name = 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.47" + Chr(34) + ".name") authAttrSigningCertificateV2Der = 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.47" + Chr(34) + ".der") j = j + 1 Wend EndIf i = i + 1 Wend If success <> 1 Debug CkCrypt2::ckLastErrorText(crypt) Debug "CAdES-T verification failed." Else Debug "CAdES-T signature is valid." EndIf CkJsonObject::ckDispose(json) CkCrypt2::ckDispose(crypt) CkJsonObject::ckDispose(cmsOptions) CkDtObj::ckDispose(signingTime) CkDtObj::ckDispose(authAttrSigningTimeUtctime) CkDtObj::ckDispose(unauthAttrTimestampTokenTstInfoGenTime) ProcedureReturn EndProcedure |
© 2000-2024 Chilkat Software, Inc. All Rights Reserved.