managing the signature of XML files

Angelo Messina

Active Member
Licensed User
Longtime User
Hello everyone,
you can recommend me a library to use with B4A for managing the signature of XML files
(like https://cryptosys.net/sc14n/) or similar.
I have lost more than 3 months so far to solve this problem.
always grateful thank you

REST API Devices
API for the use of the management and transmission services of the Fees. Where the term signed file is used, reference is made to a file in xml format signed with Xml Signature conforming to a specific element of an xml schema where the Signature element contains the XML signature. The definition of the XML signature format can be found at http://www.w3.org/TR/xmldsig-core/ (http://www.w3.org/TR/xmldsig-core/). The XML signature is profiled to facilitate interoperability, in particular:
within the Signature element there is no optional Object element
within the SignedInfo element there is a single Reference element that identifies the entire document (URI = "")
only the canonicalization algorithm is used http://www.w3.org/TR/2001/RECxml-c14n-20010315 as defined in http://www.w3.org/TR/xml-c14n (http: // www.w3.org/TR/xmlc14n)
only the signature algorithm is used http://www.w3.org/2001/04/xmldsig-more#rsasha256 as defined in http://www.w3.org/TR/xmldsig-core/ (http: / /www.w3.org/TR/xmldsig-core/)
only the hash algorithm is used http://www.w3.org/2001/04/xmlenc#sha256 as defined in http://www.w3.org/TR/xmlenc-core/ (http: // www .w3.org / TR / xmlenc-core /)
the transformation to be applied during the signature generation phase is the one defined in http://www.w3.org/TR/xmldsig-core/ (http://www.w3.org/TR/xmldsig-core/) as
http://www.w3.org/2000/09/xmldsig#envelopedsignature
the KeyInfo element contains only the signature key certificate

I have to send data to the Italian tax agency and use xml files to sign.
I attach an example

the first is the request for a certificate

<?xml version="1.0" encoding="UTF-8"?>
<RichiestaCertificatoDispositivo>
<Csr>MII.......NZ</Csr>
<Dispositivo>
<Tipo>DM</Tipo>
</Dispositivo>
<TecnicoVerificatore>
<CodiceFiscale>FISCALCOD</CodiceFiscale>
<PIvaSocieta>
<IdPaese>IT</IdPaese>
<IdCodice>099999999999</IdCodice>
</PIvaSocieta>
</TecnicoVerificatore>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>MZM....=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>kQRk....

==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIE.............
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
</RichiestaCertificatoDispositivo>

the second is activation

<?xml version="1.0" encoding="utf-8"?>
<p:AttivaDispositivo versione="1.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:p="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/corrispettivi/v1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Gestore>
<IdPaese>IT</IdPaese>
<IdCodice>09999999999</IdCodice>
</Gestore>
<TecnicoVerificatore>
<CodiceFiscale>FISCALCOD</CodiceFiscale>
<PIvaSocieta>
<IdPaese>IT</IdPaese>
<IdCodice>PERSONALCOD</IdCodice>
</PIvaSocieta>
</TecnicoVerificatore><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>c7hs..==</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>AEO...........==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIEx...</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
</p:AttivaDispositivo>

and the third is the transmission of the sales amounts
<?xml version="1.0" encoding="utf-8"?>
<p:DatiCorrispettivi xmlns:p="http://ivaservizi.agenziaentrate.gov.it/docs/xsd/corrispettivi/dati/v1.0" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" versione="COR10">
<Trasmissione>
<Progressivo>4</Progressivo>
<Formato>COR10</Formato>
<Dispositivo>
<Tipo>DA</Tipo>
<IdDispositivo>0535989COG00000000</IdDispositivo>
<GeoLocalizzazione>
<Lat>38.13</Lat>
<Long>13.34</Long>
</GeoLocalizzazione>
</Dispositivo>
</Trasmissione>
<DataOraRilevazione>2018-01-04T12:24:00</DataOraRilevazione>
<DatiDA>
<Cumulato>
<Venduto>720.56</Venduto>
<VendutoContante>720.56</VendutoContante>
<VendutoNoContante>0.00</VendutoNoContante>
<Incassato>1386.70</Incassato>
<IncassatoRicarica>0.00</IncassatoRicarica>
<IncassatoVendita>1369.40</IncassatoVendita>
<TotaleResoTubiResto>628.90</TotaleResoTubiResto>
<TotaleCaricatoTubiResto>642.90</TotaleCaricatoTubiResto>
<TotaleResoManualeTubiResto>0.00</TotaleResoManualeTubiResto>
<TotaleCaricatoManualeTubiResto>17.30</TotaleCaricatoManualeTubiResto>
</Cumulato>
</DatiDA><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
<ds:Reference URI="">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>AL..=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>ek...c0M==</ds:SignatureValue>
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>MIIE..==</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</ds:Signature>
</p:DatiCorrispettivi>
 
Last edited:

Angelo Messina

Active Member
Licensed User
Longtime User
Today it doesn't work, better this url
https://assistenza.agenziaentrate.g...ttr.asp?New,Kb=FattElettr_UIKIT,t=startup.tem

corrispettivi

With the system of fees, the Producer (also called "Manufacturer") requires the certificate with which the PKCS # 10 requests for instrument certificates will be signed, which will transmit the fees.
It is important to point out that this user represents the different types of operators that interface with the system, such as those who prepare the different instruments that will have to carry out the transmission of the fees.

https://www.agenziaentrate.gov.it/p...ributori-vending-senza-porta-di-comunicazione
 
Last edited:

Angelo Messina

Active Member
Licensed User
Longtime User
Hi, if it can help you
in the Windows environment the problem does not exist as the java javax package solves the problem very well and quickly
this is the source and it works

B4X:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

public class FirmaCorrispettivi {

    public static final String SHA256_RSA_SIGNATURE_ALGORITHM = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

    public static void main(String[] args)
    {
        try {
            String p12file = "C:\\Users\\Administrator\\Desktop\\xxxcrt.p12";
            String p12pass = ""; \\ password
            String infile = "C:\\Users\\Administrator\\Desktop\\OUT_1.xml";   //  "file to sign.xml";
            String signedfile = infile.replace(".xml","Firmato.xml");         // "file signature.xml";
            Provider provider = null;
//            /*
//            provider = xml.XMLUtils.getXmlDsigProvider();
//            System.out.println("XML provider: " + provider);
//            */
            X509Certificate signerCert = null;
            PrivateKey key = null;
            KeyStore ks = KeyStore.getInstance("PKCS12");
            ks.load(new FileInputStream(p12file), p12pass.toCharArray());
            Enumeration<String> en = ks.aliases();
            while (en.hasMoreElements())
            {
                String alias = (String) en.nextElement();

                if (ks.isKeyEntry(alias))
                {
                    signerCert = (X509Certificate) ks.getCertificate(alias);
                    key = (PrivateKey) ks.getKey(alias, p12pass.toCharArray());
                    break;
                }
            }
        
            if (signerCert == null || key == null)
            {
                throw new Exception("Key or Certificate not found!!");
            }

            // Create a DOM XMLSignatureFactory that will be used to generate the
            // enveloped signature
            XMLSignatureFactory fac;
            if (provider == null)
            {
                fac = XMLSignatureFactory.getInstance("DOM");
            }
            else
            {
                fac = XMLSignatureFactory.getInstance("DOM", provider);
            }
      
            // Create a Reference to the enveloped document (in this case we are
            // signing the whole document, so a URI of "" signifies that) and
            // also specify the SHA1 digest algorithm and the ENVELOPED Transform.
            Reference ref = fac.newReference("",fac.newDigestMethod(DigestMethod.SHA256, null),
            Collections.singletonList(fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), null,null);
      
            // Create the SignedInfo
            SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null),
            fac.newSignatureMethod(SHA256_RSA_SIGNATURE_ALGORITHM, null),Collections.singletonList(ref));
      
            KeyInfoFactory kif;
            if (provider == null)
            {
                kif = KeyInfoFactory.getInstance("DOM");
            }
            else
            {
                kif = KeyInfoFactory.getInstance("DOM", provider);
            }
      
            List x509DataContent = new ArrayList();
            x509DataContent.add(signerCert);
        
            X509Data x509Data = kif.newX509Data(x509DataContent);
            List keyInfoContent = new ArrayList();
            keyInfoContent.add(x509Data);
            KeyInfo ki = kif.newKeyInfo(keyInfoContent);

        
            // Instantiate the document to be signed
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            dbf.setValidating(true);
        
            // default false
            // dbf.setIgnoringElementContentWhitespace(true);
            // default true
            // dbf.setExpandEntityReferences(false);
            Document doc = null;
            doc = dbf.newDocumentBuilder().parse(new FileInputStream(infile));

            // Create a DOMSignContext and specify the RSA PrivateKey and
            // location of the resulting XMLSignature's parent element
            DOMSignContext dsc = new DOMSignContext(key, doc.getDocumentElement());
            dsc.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE);
            dsc.putNamespacePrefix(XMLSignature.XMLNS, "ds");

        
            // Create the XMLSignature (but don't sign it yet)
            XMLSignature signature = fac.newXMLSignature(si, ki);
      
            // Marshal, generate (and sign) the enveloped signature
            signature.sign(dsc);

            // output the resulting document
            OutputStream os;

            if (signedfile.isEmpty())
            {
                os = System.out;
            }
            else
            {
                os = new FileOutputStream(signedfile);
            }
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer trans = tf.newTransformer();
            trans.transform(new DOMSource(doc), new StreamResult(os));
            System.out.println("File " + signedfile + " signed ");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
 
Last edited:

Angelo Messina

Active Member
Licensed User
Longtime User
hi, I bother you for news for my problem, let me know how much it costs, otherwise I try to solve with something else. momentarily I have implemented a server to sign and it works well. the java source I posted worked but is implemented as you see with the javax package which is not usable with B4A. but it is an excellent starting point. thanks.
 

Raeeskhan

New Member
Hi, if it can help you
in the Windows environment the problem does not exist as the java javax package solves the problem very well and quickly
this is the source and it works

B4X:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
import javax.xml.crypto.dsig.keyinfo.X509Data;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

public class FirmaCorrispettivi {

    public static final String SHA256_RSA_SIGNATURE_ALGORITHM = "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256";

    public static void main(String[] args)
    {
        try {
            String p12file = "C:\\Users\\Administrator\\Desktop\\xxxcrt.p12";
            String p12pass = ""; \\ password
            String infile = "C:\\Users\\Administrator\\Desktop\\OUT_1.xml";   //  "file to sign.xml";
            String signedfile = infile.replace(".xml","Firmato.xml");         // "file signature.xml";
            Provider provider = null;
//            /*
//            provider = xml.XMLUtils.getXmlDsigProvider();
//            System.out.println("XML provider: " + provider);
//            */
            X509Certificate signerCert = null;
            PrivateKey key = null;
            KeyStore ks = KeyStore.getInstance("PKCS12");
            ks.load(new FileInputStream(p12file), p12pass.toCharArray());
            Enumeration<String> en = ks.aliases();
            while (en.hasMoreElements())
            {
                String alias = (String) en.nextElement();

                if (ks.isKeyEntry(alias))
                {
                    signerCert = (X509Certificate) ks.getCertificate(alias);
                    key = (PrivateKey) ks.getKey(alias, p12pass.toCharArray());
                    break;
                }
            }
       
            if (signerCert == null || key == null)
            {
                throw new Exception("Key or Certificate not found!!");
            }

            // Create a DOM XMLSignatureFactory that will be used to generate the
            // enveloped signature
            XMLSignatureFactory fac;
            if (provider == null)
            {
                fac = XMLSignatureFactory.getInstance("DOM");
            }
            else
            {
                fac = XMLSignatureFactory.getInstance("DOM", provider);
            }
     
            // Create a Reference to the enveloped document (in this case we are
            // signing the whole document, so a URI of "" signifies that) and
            // also specify the SHA1 digest algorithm and the ENVELOPED Transform.
            Reference ref = fac.newReference("",fac.newDigestMethod(DigestMethod.SHA256, null),
            Collections.singletonList(fac.newTransform(Transform.ENVELOPED, (TransformParameterSpec) null)), null,null);
     
            // Create the SignedInfo
            SignedInfo si = fac.newSignedInfo(fac.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec) null),
            fac.newSignatureMethod(SHA256_RSA_SIGNATURE_ALGORITHM, null),Collections.singletonList(ref));
     
            KeyInfoFactory kif;
            if (provider == null)
            {
                kif = KeyInfoFactory.getInstance("DOM");
            }
            else
            {
                kif = KeyInfoFactory.getInstance("DOM", provider);
            }
     
            List x509DataContent = new ArrayList();
            x509DataContent.add(signerCert);
       
            X509Data x509Data = kif.newX509Data(x509DataContent);
            List keyInfoContent = new ArrayList();
            keyInfoContent.add(x509Data);
            KeyInfo ki = kif.newKeyInfo(keyInfoContent);

       
            // Instantiate the document to be signed
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            dbf.setNamespaceAware(true);
            dbf.setValidating(true);
       
            // default false
            // dbf.setIgnoringElementContentWhitespace(true);
            // default true
            // dbf.setExpandEntityReferences(false);
            Document doc = null;
            doc = dbf.newDocumentBuilder().parse(new FileInputStream(infile));

            // Create a DOMSignContext and specify the RSA PrivateKey and
            // location of the resulting XMLSignature's parent element
            DOMSignContext dsc = new DOMSignContext(key, doc.getDocumentElement());
            dsc.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE);
            dsc.putNamespacePrefix(XMLSignature.XMLNS, "ds");

       
            // Create the XMLSignature (but don't sign it yet)
            XMLSignature signature = fac.newXMLSignature(si, ki);
     
            // Marshal, generate (and sign) the enveloped signature
            signature.sign(dsc);

            // output the resulting document
            OutputStream os;

            if (signedfile.isEmpty())
            {
                os = System.out;
            }
            else
            {
                os = new FileOutputStream(signedfile);
            }
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer trans = tf.newTransformer();
            trans.transform(new DOMSource(doc), new StreamResult(os));
            System.out.println("File " + signedfile + " signed ");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}
Hi did you solved this on android
 
Top