Sample code for 30+ languages & platforms
PureBasic

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