Sample code for 30+ languages & platforms
PureBasic

Add EncapsulatedTimestamp to Already-Signed XML

See more XML Digital Signatures Examples

Demonstrates how to add an EncapsulatedTimestamp to an existing XML signature.

Note: This example requires Chilkat v9.5.0.90 or greater.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkStringBuilder.pb"
IncludeFile "CkXmlDSig.pb"
IncludeFile "CkJsonObject.pb"

Procedure ChilkatExample()

    success.i = 0

    ; This example requires the Chilkat API to have been previously unlocked.
    ; See Global Unlock Sample for sample code.

    ; Note: We cannot load the already-signed XML into a Chilkat XML object because it would re-format the XML when re-emitted.
    ; (i.e. indentation and whitespace could change, and it would invalidate the existing signature.)
    ; We must use a StringBuilder.
    sbXml.i = CkStringBuilder::ckCreate()
    If sbXml.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkStringBuilder::ckLoadFile(sbXml,"qa_data/xml_dsig_valid_samples/encapsulatedTimestamp_not_yet_added.xml","utf-8")
    If success = 0
        Debug "Failed to load the XML file."
        CkStringBuilder::ckDispose(sbXml)
        ProcedureReturn
    EndIf

    dsig.i = CkXmlDSig::ckCreate()
    If dsig.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkXmlDSig::ckLoadSignatureSb(dsig,sbXml)
    If success = 0
        Debug CkXmlDSig::ckLastErrorText(dsig)
        CkStringBuilder::ckDispose(sbXml)
        CkXmlDSig::ckDispose(dsig)
        ProcedureReturn
    EndIf

    If CkXmlDSig::ckHasEncapsulatedTimeStamp(dsig) = 1
        Debug "This signed XML already has an EncapsulatedTimeStamp"
        CkStringBuilder::ckDispose(sbXml)
        CkXmlDSig::ckDispose(dsig)
        ProcedureReturn
    EndIf

    ; Specify the timestamping authority URL
    json.i = CkJsonObject::ckCreate()
    If json.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkJsonObject::ckUpdateString(json,"timestampToken.tsaUrl","http://timestamp.digicert.com")
    CkJsonObject::ckUpdateBool(json,"timestampToken.requestTsaCert",1)

    ; Call AddEncapsulatedTimeStamp to add the EncapsulatedTimeStamp to the signature.
    ; Note: If the signed XML contains multiple signatures, the signature modified is the one 
    ; indicated by the dsig.Selector property.
    sbOut.i = CkStringBuilder::ckCreate()
    If sbOut.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkXmlDSig::ckAddEncapsulatedTimeStamp(dsig,json,sbOut)
    If success = 0
        Debug CkXmlDSig::ckLastErrorText(dsig)
        CkStringBuilder::ckDispose(sbXml)
        CkXmlDSig::ckDispose(dsig)
        CkJsonObject::ckDispose(json)
        CkStringBuilder::ckDispose(sbOut)
        ProcedureReturn
    EndIf

    CkStringBuilder::ckWriteFile(sbOut,"qa_output/addedEncapsulatedTimeStamp.xml","utf-8",0)

    ; The EncapsulatedTimeStamp can be validated when validating the signature by adding the VerifyEncapsulatedTimeStamp
    ; keyword to UncommonOptions.  See here:

    ; ----------------------------------------
    ; Verify the signatures we just produced...
    verifier.i = CkXmlDSig::ckCreate()
    If verifier.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkXmlDSig::ckLoadSignatureSb(verifier,sbOut)
    If success <> 1
        Debug CkXmlDSig::ckLastErrorText(verifier)
        CkStringBuilder::ckDispose(sbXml)
        CkXmlDSig::ckDispose(dsig)
        CkJsonObject::ckDispose(json)
        CkStringBuilder::ckDispose(sbOut)
        CkXmlDSig::ckDispose(verifier)
        ProcedureReturn
    EndIf

    ; Add "VerifyEncapsulatedTimeStamp" to the UncommonOptions to also verify any EncapsulatedTimeStamps
    CkXmlDSig::setCkUncommonOptions(verifier, "VerifyEncapsulatedTimeStamp")

    numSigs.i = CkXmlDSig::ckNumSignatures(verifier)
    verifyIdx.i = 0
    While verifyIdx < numSigs
        CkXmlDSig::setCkSelector(verifier, verifyIdx)
        verified.i = CkXmlDSig::ckVerifySignature(verifier,1)
        If verified <> 1
            Debug CkXmlDSig::ckLastErrorText(verifier)
            CkStringBuilder::ckDispose(sbXml)
            CkXmlDSig::ckDispose(dsig)
            CkJsonObject::ckDispose(json)
            CkStringBuilder::ckDispose(sbOut)
            CkXmlDSig::ckDispose(verifier)
            ProcedureReturn
        EndIf

        verifyIdx = verifyIdx + 1
    Wend
    Debug "All signatures were successfully verified."


    CkStringBuilder::ckDispose(sbXml)
    CkXmlDSig::ckDispose(dsig)
    CkJsonObject::ckDispose(json)
    CkStringBuilder::ckDispose(sbOut)
    CkXmlDSig::ckDispose(verifier)


    ProcedureReturn
EndProcedure