Firma digitale: il formato XAdES

XAdES (XML Advanced Electronic Signature) la firma digitale basata sul XML
Data: 24/04/2016 Autore: Iasparra Francesco 

La firma digitale XAdES permette di firmare un file XML e di rappresentare il risultato della firma sempre nel formato XML.

Caratteristica dello XAdES e' la possibilita' di firmare singole parti del documento, cosa di particolare importanza nei caso di documenti scritti da piu' persone, in cui ognuno deve firmare la sua parte.

La rappresentazione dei dati in XML permette la lettura tramite un semplice editor,ma risulta poco leggibile ed e' quindi solitamente abbinato un file di presentazione XSLT che ne determina la creazione del documento di facile leggibilita'.

Quindi possono esistere problematiche correlate alla possibile diversa rappresentazione visiva dei dati di uno stesso file XML, ad esempio utilizzando due diversi file XSLT. Il firmatario potrebbe firmare un file rappresentato in modo diverso dalla rappresentazione visiva per il destinatario e questo potrebbe creare indubbiamente probblemi.

Qui di seguito viene riportato l'esempio di firma XAdES-BES, il formato usato per firmare le fatture PA, con struttura aderente alla specifica pubblica ETSI TS 101 903 versione 1.4.1, cosi come previsto dalla normativa in materia a partire dal 1 settembre 2010:

String xadesNS="http://uri.etsi.org/01903/v1.3.2#";
String dsNS = "http://www.w3.org/2000/09/xmldsig#";
String signedPropID="SignedProperties_1";
String signatureID="Signature1";
String signatureValueID="SignatureValue1";
String prefixNameSpaceXades="xades:";
char[] pinC="password".toCharArray();
File testKeyStore=new File("keystore.p12");
FileInputStream pkcs12file=new FileInputStream(testKeyStore);
KeyStore ks=KeyStore.getInstance("PKCS12");
ks.load(pkcs12file,pinC);
KeyStore.ProtectionParameter pp=new KeyStore.PasswordProtection(pinC);
Enumeration list=ks.aliases();
while(list.hasMoreElements()) {
    String alias = (String) list.nextElement();
    KeyStore.Entry entry = ks.getEntry(alias, pp);
    boolean isPrivateKeyEntry = ks.entryInstanceOf(alias, KeyStore.PrivateKeyEntry.class);
    if (isPrivateKeyEntry){
        KeyStore.PrivateKeyEntry privateKeyEntry = (KeyStore.PrivateKeyEntry)entry;
        PrivateKey pk = privateKeyEntry.getPrivateKey();
        java.security.cert.Certificate[] chainx = privateKeyEntry.getCertificateChain();
        ArrayList<X509Certificate> certsin=new ArrayList<X509Certificate>();        for (int i=0;i<chainx.length;i++) certsin.add((X509Certificate) chainx[i]);        X509Certificate cert=certsin.get(0);  

String providerName = System.getProperty("jsr105Provider", "org.jcp.xml.dsig.internal.dom.XMLDSigRI");
Provider provider = (Provider) Class.forName(providerName).newInstance();
XMLSignatureFactory sigFactory = XMLSignatureFactory.getInstance("DOM",provider);
System.out.println("Provider="+sigFactory.getProvider().getName());
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = dbf.newDocumentBuilder();
Document doc  = builder.parse(new File("etc/example.xml"));
final Document docDest = builder.newDocument();
Node objContent = docDest.importNode(doc.getDocumentElement(),true);
docDest.appendChild(objContent);
List<Reference> refs = new ArrayList<Reference>();List<XPathType> xpaths = new ArrayList<XPathType>();xpaths.add(new XPathType("/descendant::ds:Signature", XPathType.Filter.SUBTRACT));
Reference ref1 = sigFactory.newReference("", sigFactory.newDigestMethod(DigestMethod.SHA1, null),
Collections.singletonList(sigFactory.newTransform(Transform.XPATH2, new XPathFilter2ParameterSpec(xpaths))),null, 
"reference-document"); 
refs.add(ref1);
Reference ref2 = sigFactory.newReference("#"+signedPropID,sigFactory.newDigestMethod(DigestMethod.SHA1,null),null,
xadesNS+"SignedProperties","reference-signedpropeties");
refs.add(ref2);      
CanonicalizationMethod cm=sigFactory.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE,
(C14NMethodParameterSpec) null);
SignatureMethod sm=sigFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, null);
SignedInfo si = sigFactory.newSignedInfo(cm,sm,refs);
    KeyInfoFactory kif = sigFactory.getKeyInfoFactory();
    X509Data xd = kif.newX509Data(Collections.singletonList(cert));
    KeyInfo ki = kif.newKeyInfo(Collections.singletonList(xd));
    DOMSignContext dsc = new DOMSignContext(pk,objContent);
    dsc.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE);
    dsc.putNamespacePrefix(dsNS, "ds");
    XMLObject xades=xadesProperty(sigFactory, docDest, cert);
    List<XMLObject> objects = new ArrayList<XMLObject>();    objects.add(xades);
    XMLSignature signature = sigFactory.newXMLSignature(si, ki, objects, signatureID, signatureValueID);
    signature.sign(dsc);    
    FileOutputStream out = new FileOutputStream("signed.xml");
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer trans = tf.newTransformer();
    trans.setOutputProperty(OutputKeys.INDENT, "yes");
    trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8");            
    trans.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
    trans.transform(new DOMSource(docDest),new StreamResult(out));
    out.close();
   }
}    

Il metodo xadesProperty restituisce un oggetto XML che continene le proprieta' di firma SignedProperties.
Un esempio possibile e' qui sotto riportato:
public static XMLObject xadesProperty(XMLSignatureFactory sigFactory,Document doc, X509Certificate cert)throws Exception{
    Element QElement = doc.createElementNS(xadesNS, "xades:QualifyingProperties");
    QElement.setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xades", xadesNS);
    QElement.setAttributeNS(null, "Target", "#" + IDSig);
    Element SElement = doc.createElementNS(xadesNS,"xades:SignedProperties");
    SElement.setAttributeNS(null, "Id", IDSP);   
    SElement.setIdAttribute("Id", true);
    QElement.appendChild(SElement);
    Element SignedSignaturePropertiesElement = doc.createElementNS(xadesNS,"xades:SignedSignatureProperties");   
    SElement.appendChild(SignedSignaturePropertiesElement);
    Element SigningTimeElement = doc.createElementNS(xadesNS, "xades:SigningTime");
    String data = "2016-06-28T16:47:50Z";
    SigningTimeElement.setTextContent(data);
    SignedSignaturePropertiesElement.appendChild(SigningTimeElement);
    Element SigningCertificateElement = doc.createElementNS(xadesNS, "xades:SigningCertificate");
    SignedSignaturePropertiesElement.appendChild(SigningCertificateElement);
    Element CertElement = doc.createElementNS(xadesNS, "xades:Cert");
    SigningCertificateElement.appendChild(CertElement);
    Element CertDigestElement = doc.createElementNS(xadesNS, "xades:CertDigest");
    CertElement.appendChild(CertDigestElement);
    Element DigestMethodElement = doc.createElementNS(dsNS, "ds:DigestMethod");
    DigestMethodElement.setAttributeNS(null, "Algorithm","http://www.w3.org/2000/09/xmldsig#sha1");
    CertDigestElement.appendChild(DigestMethodElement);
    Element DigestValueElement = doc.createElementNS(dsNS, "ds:DigestValue");
    String hash = Utils.digestInputEqualB64(cert.getEncoded(), "SHA1");
    DigestValueElement.setTextContent(hash);
    CertDigestElement.appendChild(DigestValueElement);
    Element IssuerSerialElement = doc.createElementNS(xadesNS, "xades:IssuerSerial");
    CertElement.appendChild(IssuerSerialElement);
    Element X509IssuerNameElement = doc.createElementNS(dsNS, "ds:X509IssuerName");
    X509IssuerNameElement.setTextContent(cert.getIssuerDN().getName());
    IssuerSerialElement.appendChild(X509IssuerNameElement);
    Element X509SerialNumberElement = doc.createElementNS(dsNS, "ds:X509SerialNumber");
    X509SerialNumberElement.setTextContent(cert.getSerialNumber().toString());
    IssuerSerialElement.appendChild(X509SerialNumberElement);
    DOMStructure qualifPropStruct = new DOMStructure(QElement);
    List xmlObj = new ArrayList();
    xmlObj.add(qualifPropStruct);
    XMLObject object = sigFactory.newXMLObject(xmlObj, null, null, null);
    return object;
}    



  • Java
  • Php
  • Mysql
  • Apache ant
  • Eclipse
  • Spring
  • Hibernate
  • Netbeans
  • Debian
  • Linux
  • Maven

by Iasparra Francesco - © Copyright 2021

E' vietata la riproduzione anche parziale dei materiali presenti in questo sito.

I marchi e le immagini esposti sono Copyright dei rispettivi proprietari.