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

SII Chile - FRMT Signature Computation and Add to XML

See more XML Digital Signatures Examples

Compute the FRMT signature and add to the XML. This is the RSA signature of the SHA-1 digest of the "flattened" DD element.

Chilkat PureBasic Downloads

PureBasic
IncludeFile "CkXml.pb"
IncludeFile "CkStringBuilder.pb"
IncludeFile "CkPrivateKey.pb"
IncludeFile "CkRsa.pb"

Procedure ChilkatExample()

    success.i = 0

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

    ;  Also see:  Compute the FRMA Signature and Add to XML

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

    ;  Load the unsigned XML that contains the following:

    ;  <DTE version="1.0">
    ;    <Documento ID="F60T33">
    ;          <TED version="1.0">
    ;              <DD>
    ;  		...
    ;                  <CAF version="1.0">
    ;                      <DA>
    ;  			...
    ;                      </DA>
    ;                      <FRMA algoritmo="SHA1withRSA">...</FRMA>
    ;                  </CAF>
    ;                  ...
    ;              </DD>
    ;              ... The FRMT will be added here in another example ...
    ;          </TED>
    ;    </Documento>
    ;  </DTE>

    success = CkXml::ckLoadXmlFile(xml,"qa_data/xml_dsig/sii_cl/test_1.xml")
    If success = 0
        Debug "Failed to load initial XML file."
        CkXml::ckDispose(xml)
        ProcedureReturn
    EndIf

    ;  Get a reference to the "DD" element
    ddXml.i = CkXml::ckFindChild(xml,"Documento|TED|DD")
    If CkXml::ckLastMethodSuccess(xml) = 0
        Debug "Failed to find DD element"
        CkXml::ckDispose(xml)
        ProcedureReturn
    EndIf

    ;   We need to get the "flattened" DD XML where:
    ;     - No whitespace between elements.
    ;     - The 5 pre-defined entities are converted.
    ;     - The text is encoded in the ISO-8859-1 character set (Latin-1), 
    sbFlattened.i = CkStringBuilder::ckCreate()
    If sbFlattened.i = 0
        Debug "Failed to create object."
        ProcedureReturn
    EndIf

    CkXml::setCkEmitCompact(ddXml, 1)
    CkXml::setCkEmitXmlDecl(ddXml, 0)
    CkXml::ckGetXmlSb(ddXml,sbFlattened)

    ;  Compute the SHA-1 message digest of the iso-8859-1 byte representation, 
    ;  and sign it with our RSA private key, getting the result in base64 format.

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

    success = CkPrivateKey::ckLoadAnyFormatFile(privKey,"qa_data/rsa/rsaPrivKey_pkcs8.pem","")
    If success = 0
        Debug CkPrivateKey::ckLastErrorText(privKey)
        CkXml::ckDispose(xml)
        CkStringBuilder::ckDispose(sbFlattened)
        CkPrivateKey::ckDispose(privKey)
        ProcedureReturn
    EndIf

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

    CkRsa::ckUsePrivateKey(rsa,privKey)

    CkRsa::setCkEncodingMode(rsa, "base64")
    CkRsa::setCkCharset(rsa, "iso-8859-1")
    sig.s = CkRsa::ckSignStringENC(rsa,CkStringBuilder::ckGetAsString(sbFlattened),"sha1")

    ;  Add the FRMT signature element to the XML.
    CkXml::ckUpdateChildContent(xml,"Documento|TED|FRMT",sig)
    CkXml::ckUpdateAttrAt(xml,"Documento|TED|FRMT",1,"algoritmo","SHA1withRSA")

    CkXml::ckDispose(ddXml)

    ;  See what we have:
    CkXml::setCkEmitCompact(xml, 0)
    CkXml::setCkEmitXmlDecl(xml, 1)
    Debug CkXml::ckGetXml(xml)


    CkXml::ckDispose(xml)
    CkStringBuilder::ckDispose(sbFlattened)
    CkPrivateKey::ckDispose(privKey)
    CkRsa::ckDispose(rsa)


    ProcedureReturn
EndProcedure