Sample code for 30+ languages & platforms
Lianja

XML-DSig Add Reference with Transforms Specified Explicitly

Demonstrates how to use the new AddSameDocRef2 method to explicitly specify the XML Transforms fragment.

Chilkat Lianja Downloads

Lianja
llSuccess = .F.

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

llSuccess = .T.

// Create the following XML to be signed:

// <doc>
//     <s id="s1">Some text...</s>
//     <p>Some text...</p>
//     <p class="note">A note...</p>
// </doc>

// Use this online tool to generate code from sample XML: 
// Generate Code to Create XML

loXmlToSign = createobject("CkXml")
loXmlToSign.Tag = "doc"
loXmlToSign.UpdateAttrAt("s",.T.,"id","s1")
loXmlToSign.UpdateChildContent("s","Some text...")
loXmlToSign.UpdateChildContent("p","Some text...")
loXmlToSign.UpdateAttrAt("p[1]",.T.,"class","note")
loXmlToSign.UpdateChildContent("p[1]","A note...")

? loXmlToSign.GetXml()

loGen = createobject("CkXmlDSigGen")

loGen.SigLocation = "doc"
loGen.SigLocationMod = 0
loGen.SigId = "Signature-78f29839-06af-448f-b479-ca46457fab1b-Signature"
loGen.SigNamespacePrefix = "ds"
loGen.SigNamespaceUri = "http://www.w3.org/2000/09/xmldsig#"
loGen.SigValueId = "Signature-78f29839-06af-448f-b479-ca46457fab1b-SignatureValue"
loGen.SignedInfoCanonAlg = "C14N"
loGen.SignedInfoDigestMethod = "sha1"

// Set the KeyInfoId before adding references..
loGen.KeyInfoId = "Signature-78f29839-06af-448f-b479-ca46457fab1b-KeyInfo"

// The following XML to be added as an Object to the Signature

// Use this online tool to generate code from sample XML: 
// Generate Code to Create XML

// <xades:QualifyingProperties Id="Signature-78f29839-06af-448f-b479-ca46457fab1b-QualifyingProperties" Target="#Signature-78f29839-06af-448f-b479-ca46457fab1b-Signature" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xades="http://uri.etsi.org/01903/v1.3.2#">
//     <xades:SignedProperties Id="Signature-78f29839-06af-448f-b479-ca46457fab1b-SignedProperties">
//         <xades:SignedSignatureProperties>
//             <xades:SigningTime>TO BE GENERATED BY CHILKAT</xades:SigningTime>
//             <xades:SigningCertificate>
//                 <xades:Cert>
//                     <xades:CertDigest>
//                         <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
//                         <ds:DigestValue>TO BE GENERATED BY CHILKAT</ds:DigestValue>
//                     </xades:CertDigest>
//                     <xades:IssuerSerial>
//                         <ds:X509IssuerName>TO BE GENERATED BY CHILKAT</ds:X509IssuerName>
//                         <ds:X509SerialNumber>TO BE GENERATED BY CHILKAT</ds:X509SerialNumber>
//                     </xades:IssuerSerial>
//                 </xades:Cert>
//             </xades:SigningCertificate>
//         </xades:SignedSignatureProperties>
//         <xades:SignedDataObjectProperties>
//             <xades:DataObjectFormat ObjectReference="#Reference-24eb6003-d41c-442c-a731-d4c58f94790b">
//                 <xades:Description/>
//                 <xades:ObjectIdentifier>
//                     <xades:Identifier Qualifier="OIDAsURN">urn:oid:1.2.840.10003.5.109.10</xades:Identifier>
//                     <xades:Description/>
//                 </xades:ObjectIdentifier>
//                 <xades:MimeType>text/xml</xades:MimeType>
//                 <xades:Encoding/>
//             </xades:DataObjectFormat>
//         </xades:SignedDataObjectProperties>
//     </xades:SignedProperties>
// </xades:QualifyingProperties>

loObject1 = createobject("CkXml")
loObject1.Tag = "xades:QualifyingProperties"
loObject1.AddAttribute("Id","Signature-78f29839-06af-448f-b479-ca46457fab1b-QualifyingProperties")
loObject1.AddAttribute("Target","#Signature-78f29839-06af-448f-b479-ca46457fab1b-Signature")
loObject1.AddAttribute("xmlns:ds","http://www.w3.org/2000/09/xmldsig#")
loObject1.AddAttribute("xmlns:xades","http://uri.etsi.org/01903/v1.3.2#")
loObject1.UpdateAttrAt("xades:SignedProperties",.T.,"Id","Signature-78f29839-06af-448f-b479-ca46457fab1b-SignedProperties")
loObject1.UpdateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningTime","TO BE GENERATED BY CHILKAT")
// Note: It may be that http://www.w3.org/2001/04/xmlenc#sha256 is needed in the following line instead of http://www.w3.org/2000/09/xmldsig#sha1
loObject1.UpdateAttrAt("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:CertDigest|ds:DigestMethod",.T.,"Algorithm","http://www.w3.org/2000/09/xmldsig#sha1")
loObject1.UpdateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:CertDigest|ds:DigestValue","TO BE GENERATED BY CHILKAT")
loObject1.UpdateChildContent("xades:SignedProperties|xades:SignedSignatureProperties|xades:SigningCertificateV2|xades:Cert|xades:IssuerSerialV2","TO BE GENERATED BY CHILKAT")
loObject1.UpdateAttrAt("xades:SignedProperties|xades:SignedDataObjectProperties|xades:DataObjectFormat",.T.,"ObjectReference","#Reference-24eb6003-d41c-442c-a731-d4c58f94790b")
loObject1.UpdateChildContent("xades:SignedProperties|xades:SignedDataObjectProperties|xades:DataObjectFormat|xades:Description","")
loObject1.UpdateAttrAt("xades:SignedProperties|xades:SignedDataObjectProperties|xades:DataObjectFormat|xades:ObjectIdentifier|xades:Identifier",.T.,"Qualifier","OIDAsURN")
loObject1.UpdateChildContent("xades:SignedProperties|xades:SignedDataObjectProperties|xades:DataObjectFormat|xades:ObjectIdentifier|xades:Identifier","urn:oid:1.2.840.10003.5.109.10")
loObject1.UpdateChildContent("xades:SignedProperties|xades:SignedDataObjectProperties|xades:DataObjectFormat|xades:ObjectIdentifier|xades:Description","")
loObject1.UpdateChildContent("xades:SignedProperties|xades:SignedDataObjectProperties|xades:DataObjectFormat|xades:MimeType","text/xml")
loObject1.UpdateChildContent("xades:SignedProperties|xades:SignedDataObjectProperties|xades:DataObjectFormat|xades:Encoding","")

? loObject1.GetXml()

loGen.AddObject("",loObject1.GetXml(),"","")

// -------- Reference 1 --------

// Create the following Transforms fragment:

// Use this online tool to generate code from sample XML: 
// Generate Code to Create XML

// <ds:Transforms>
//     <ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
//     <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
//     <ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
//         <ds:XPath xmlns:ds="http://www.w3.org/2000/09/xmldsig#">not(ancestor-or-self::ds:Signature)</ds:XPath>
//     </ds:Transform>
// </ds:Transforms>

loXml1 = createobject("CkXml")
loXml1.Tag = "ds:Transforms"
loXml1.UpdateAttrAt("ds:Transform",.T.,"Algorithm","http://www.w3.org/TR/2001/REC-xml-c14n-20010315")
loXml1.UpdateAttrAt("ds:Transform[1]",.T.,"Algorithm","http://www.w3.org/2000/09/xmldsig#enveloped-signature")
loXml1.UpdateAttrAt("ds:Transform[2]",.T.,"Algorithm","http://www.w3.org/TR/1999/REC-xpath-19991116")
loXml1.UpdateAttrAt("ds:Transform[2]|ds:XPath",.T.,"xmlns:ds","http://www.w3.org/2000/09/xmldsig#")
loXml1.UpdateChildContent("ds:Transform[2]|ds:XPath","not(ancestor-or-self::ds:Signature)")

// This is the "Transforms" XML fragment passed to AddSameDocRef2.
? loXml1.GetXml()

loGen.AddSameDocRef2("","sha1",loXml1,"")

loGen.SetRefIdAttr("","Reference-24eb6003-d41c-442c-a731-d4c58f94790b")

// -------- Reference 2 --------
loGen.AddObjectRef("Signature-78f29839-06af-448f-b479-ca46457fab1b-SignedProperties","sha1","","","http://uri.etsi.org/01903#SignedProperties")

// -------- Reference 3 --------
loGen.AddSameDocRef("Signature-78f29839-06af-448f-b479-ca46457fab1b-KeyInfo","sha1","","","")

// Provide a certificate + private key. (PFX password is test123)
loCert = createobject("CkCert")
llSuccess = loCert.LoadPfxFile("qa_data/pfx/cert_test123.pfx","test123")
if (llSuccess <> .T.) then
    ? loCert.LastErrorText
    release loXmlToSign
    release loGen
    release loObject1
    release loXml1
    release loCert
    return
endif

loGen.SetX509Cert(loCert,.T.)

loGen.KeyInfoType = "X509Data+KeyValue"
loGen.X509Type = "CertChain"

// Load XML to be signed...
loSbXml = createobject("CkStringBuilder")
loXmlToSign.GetXmlSb(loSbXml)

loGen.Behaviors = "IndentedSignature"

// Sign the XML...
llSuccess = loGen.CreateXmlDSigSb(loSbXml)
if (llSuccess <> .T.) then
    ? loGen.LastErrorText
    release loXmlToSign
    release loGen
    release loObject1
    release loXml1
    release loCert
    release loSbXml
    return
endif

// -----------------------------------------------

// Save the signed XML to a file.
llSuccess = loSbXml.WriteFile("qa_output/signedXml.xml","utf-8",.F.)

? loSbXml.GetAsString()

// ----------------------------------------
// Verify the signatures we just produced...
loVerifier = createobject("CkXmlDSig")
llSuccess = loVerifier.LoadSignatureSb(loSbXml)
if (llSuccess <> .T.) then
    ? loVerifier.LastErrorText
    release loXmlToSign
    release loGen
    release loObject1
    release loXml1
    release loCert
    release loSbXml
    release loVerifier
    return
endif

lnNumSigs = loVerifier.NumSignatures
lnVerifyIdx = 0
do while lnVerifyIdx < lnNumSigs
    loVerifier.Selector = lnVerifyIdx
    llVerified = loVerifier.VerifySignature(.T.)
    if (llVerified <> .T.) then
        ? loVerifier.LastErrorText
        release loXmlToSign
        release loGen
        release loObject1
        release loXml1
        release loCert
        release loSbXml
        release loVerifier
        return
    endif

    lnVerifyIdx = lnVerifyIdx + 1
enddo
? "All signatures were successfully verified."


release loXmlToSign
release loGen
release loObject1
release loXml1
release loCert
release loSbXml
release loVerifier