Sample code for 30+ languages & platforms
PureBasic

Create XAdES with ec:InclusiveNamespaces within the Transforms

See more XML Digital Signatures Examples

Demonstrates how to generate XAdES that has a Reference that has Transforms that include an ec:InclusiveNamespaces.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkCert.pb"
IncludeFile "CkXml.pb"
IncludeFile "CkXmlDSigGen.pb"
IncludeFile "CkXmlDSig.pb"
IncludeFile "CkStringBuilder.pb"

Procedure ChilkatExample()

    success.i = 0

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

    ; This is the XML we'll be signing:

    ; <soapenv:Envelope xmlns:obs="http://csioz.gov.pl/zsmopl/ws/obslugakomunikatow/" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
    ; 	<soapenv:Header>
    ; 		<wsse:Security 
    ; 		    xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd"
    ; 		    xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" soapenv:mustUnderstand="1">
    ; 			<wsse:BinarySecurityToken
    ; 				EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary"
    ; 				ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1"
    ; 				wsu:Id="X509-02BF0107214FC61449FD0013DF68F0359">MII...</wsse:BinarySecurityToken>
    ; 		</wsse:Security>
    ; 	</soapenv:Header>
    ; 	<soapenv:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" 
    ; 		wsu:Id="id-396BB6026342EB5C0E1EA73593B3CC098">
    ; 		<obs:zapiszKomunikatOS>
    ; 			<komunikatOS>
    ; 				<idPodmiotuRaportujacego>
    ; 					<idBiznesowy>000000011986</idBiznesowy>
    ; 					<rodzajPodmiotuRaportujacego>PA</rodzajPodmiotuRaportujacego>
    ; 				</idPodmiotuRaportujacego>
    ; 			</komunikatOS>
    ; 		</obs:zapiszKomunikatOS>
    ; 	</soapenv:Body>
    ; </soapenv:Envelope>
    ; 

    ; ----------------------------------------------------------------------
    ; IMPORTANT: This generated example requires Chilkat v9.5.0.77 or later.
    ; ----------------------------------------------------------------------
    success = 1
    ; Create the above XML to be signed...
    xmlToSign.i = CkXml::ckCreate()
    If xmlToSign.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkXml::setCkTag(xmlToSign, "soapenv:Envelope")
    CkXml::ckAddAttribute(xmlToSign,"xmlns:obs","http://csioz.gov.pl/zsmopl/ws/obslugakomunikatow/")
    CkXml::ckAddAttribute(xmlToSign,"xmlns:soapenv","http://schemas.xmlsoap.org/soap/envelope/")
    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Header|wsse:Security",1,"xmlns:wsse","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd")
    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Header|wsse:Security",1,"xmlns:wsu","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd")
    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Header|wsse:Security",1,"soapenv:mustUnderstand","1")
    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Header|wsse:Security|wsse:BinarySecurityToken",1,"EncodingType","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary")
    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Header|wsse:Security|wsse:BinarySecurityToken",1,"ValueType","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1")
    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Header|wsse:Security|wsse:BinarySecurityToken",1,"wsu:Id","X509-02BF0107214FC61449FD0013DF68F0359")
    ; Note: The content of this XML node is a placeholder that will be updated below with the X509PKIPathv1 for the signing certificate.
    CkXml::ckUpdateChildContent(xmlToSign,"soapenv:Header|wsse:Security|wsse:BinarySecurityToken","BinarySecurityToken_Base64Binary_Content")
    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Body",1,"xmlns:wsu","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd")
    CkXml::ckUpdateAttrAt(xmlToSign,"soapenv:Body",1,"wsu:Id","id-396BB6026342EB5C0E1EA73593B3CC098")
    CkXml::ckUpdateChildContent(xmlToSign,"soapenv:Body|obs:zapiszKomunikatOS|komunikatOS|idPodmiotuRaportujacego|idBiznesowy","000000011986")
    CkXml::ckUpdateChildContent(xmlToSign,"soapenv:Body|obs:zapiszKomunikatOS|komunikatOS|idPodmiotuRaportujacego|rodzajPodmiotuRaportujacego","PA")

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

    CkXmlDSigGen::setCkSigLocation(gen, "soapenv:Envelope|soapenv:Header|wsse:Security")
    CkXmlDSigGen::setCkSigLocationMod(gen, 0)
    CkXmlDSigGen::setCkSigId(gen, "SIG-BB965DFC3C8AAF87903C0ED898B8D2A8D")
    CkXmlDSigGen::setCkSigNamespacePrefix(gen, "ds")
    CkXmlDSigGen::setCkSigNamespaceUri(gen, "http://www.w3.org/2000/09/xmldsig#")
    CkXmlDSigGen::setCkSignedInfoCanonAlg(gen, "EXCL_C14N")
    CkXmlDSigGen::setCkSignedInfoDigestMethod(gen, "sha1")

    ; Set the KeyInfoId before adding references..
    CkXmlDSigGen::setCkKeyInfoId(gen, "KI-9D95C38916099AD2EE87DDAC1A76E97E4")

    ; -------- Reference 1 --------
    CkXmlDSigGen::ckAddSameDocRef(gen,"id-396BB6026342EB5C0E1EA73593B3CC098","sha1","EXCL_C14N","obs","")

    ; The reference to be produced in the Signature should look like this:

    ; <ds:Reference URI="#id-396BB6026342EB5C0E1EA73593B3CC098">
    ;     <ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
    ;         <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="obs"></ec:InclusiveNamespaces>
    ;     </ds:Transform></ds:Transforms>
    ;     <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
    ;     <ds:DigestValue>2e9hZYj/CN2nPsgQqUraU43k3ds=</ds:DigestValue>
    ; </ds:Reference>
    ; 

    ; Provide a certificate + private key. (PFX password is test123)
    cert.i = CkCert::ckCreate()
    If cert.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    success = CkCert::ckLoadPfxFile(cert,"qa_data/pfx/cert_test123.pfx","test123")
    If success <> 1
        Debug CkCert::ckLastErrorText(cert)
        CkXml::ckDispose(xmlToSign)
        CkXmlDSigGen::ckDispose(gen)
        CkCert::ckDispose(cert)
        ProcedureReturn
    EndIf

    CkXmlDSigGen::ckSetX509Cert(gen,cert,1)

    CkXmlDSigGen::setCkKeyInfoType(gen, "Custom")

    ; Create the custom KeyInfo XML..
    xmlCustomKeyInfo.i = CkXml::ckCreate()
    If xmlCustomKeyInfo.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkXml::setCkTag(xmlCustomKeyInfo, "wsse:SecurityTokenReference")
    CkXml::ckAddAttribute(xmlCustomKeyInfo,"wsse11:TokenType","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1")
    CkXml::ckAddAttribute(xmlCustomKeyInfo,"xmlns:wsse11","http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd")
    CkXml::ckAddAttribute(xmlCustomKeyInfo,"wsu:Id","STR-FF238E7C061332C5B19752C2FBC8CDEF2")
    CkXml::ckUpdateAttrAt(xmlCustomKeyInfo,"wsse:Reference",1,"URI","#X509-02BF0107214FC61449FD0013DF68F0359")
    CkXml::ckUpdateAttrAt(xmlCustomKeyInfo,"wsse:Reference",1,"ValueType","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509PKIPathv1")

    CkXml::setCkEmitXmlDecl(xmlCustomKeyInfo, 0)
    CkXmlDSigGen::setCkCustomKeyInfoXml(gen, CkXml::ckGetXml(xmlCustomKeyInfo))

    ; Load XML to be signed...
    sbXml.i = CkStringBuilder::ckCreate()
    If sbXml.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkXml::ckGetXmlSb(xmlToSign,sbXml)

    ; Update BinarySecurityToken_Base64Binary_Content with the actual X509PKIPathv1 of the signing cert.
    nReplaced.i = CkStringBuilder::ckReplace(sbXml,"BinarySecurityToken_Base64Binary_Content",CkCert::ckX509PKIPathv1(cert))

    CkXmlDSigGen::setCkBehaviors(gen, "IndentedSignature")

    ; Sign the XML...
    success = CkXmlDSigGen::ckCreateXmlDSigSb(gen,sbXml)
    If success <> 1
        Debug CkXmlDSigGen::ckLastErrorText(gen)
        CkXml::ckDispose(xmlToSign)
        CkXmlDSigGen::ckDispose(gen)
        CkCert::ckDispose(cert)
        CkXml::ckDispose(xmlCustomKeyInfo)
        CkStringBuilder::ckDispose(sbXml)
        ProcedureReturn
    EndIf

    ; -----------------------------------------------

    ; Save the signed XML to a file.
    success = CkStringBuilder::ckWriteFile(sbXml,"qa_output/signedXml.xml","utf-8",0)

    Debug CkStringBuilder::ckGetAsString(sbXml)

    ; ----------------------------------------
    ; 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,sbXml)
    If success <> 1
        Debug CkXmlDSig::ckLastErrorText(verifier)
        CkXml::ckDispose(xmlToSign)
        CkXmlDSigGen::ckDispose(gen)
        CkCert::ckDispose(cert)
        CkXml::ckDispose(xmlCustomKeyInfo)
        CkStringBuilder::ckDispose(sbXml)
        CkXmlDSig::ckDispose(verifier)
        ProcedureReturn
    EndIf

    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)
            CkXml::ckDispose(xmlToSign)
            CkXmlDSigGen::ckDispose(gen)
            CkCert::ckDispose(cert)
            CkXml::ckDispose(xmlCustomKeyInfo)
            CkStringBuilder::ckDispose(sbXml)
            CkXmlDSig::ckDispose(verifier)
            ProcedureReturn
        EndIf

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


    CkXml::ckDispose(xmlToSign)
    CkXmlDSigGen::ckDispose(gen)
    CkCert::ckDispose(cert)
    CkXml::ckDispose(xmlCustomKeyInfo)
    CkStringBuilder::ckDispose(sbXml)
    CkXmlDSig::ckDispose(verifier)


    ProcedureReturn
EndProcedure