Cifratura e Spring

Come usare le librerie di Spring per cifrare le informazioni.

Cifrare una request SOAP con BinarySecurityToken

Importare il jar  wss4j   versione  2.2.1 (ultima versione al momento)

<dependency>
<groupId>org.apache.wss4j</groupId>
<artifactId>wss4j-bindings</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.wss4j</groupId>
<artifactId>wss4j-integration</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.wss4j</groupId>
<artifactId>wss4j-ws-security-common</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>org.apache.wss4j</groupId>
<artifactId>wss4j-ws-security-dom</artifactId>
<version>2.1.1</version>
</dependency>

Creare un Handle:

WSSUsernameTokenSecurityHandler .java

package it;

import java.io.FileInputStream;
import java.io.StringWriter;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPHeader;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.handler.soap.SOAPHandler;
import javax.xml.ws.handler.soap.SOAPMessageContext;

import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.CryptoFactory;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.message.WSSecHeader;
import org.apache.wss4j.dom.message.WSSecSignature;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;

public class WSSUsernameTokenSecurityHandler implements SOAPHandler<SOAPMessageContext> {


  @Override
  public Set<QName> getHeaders() {
      final QName securityHeader = new QName(
          “http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd”,
          “Security”,
          “wsse”);

      final HashSet<QName> headers = new HashSet<QName>();
      headers.add(securityHeader);

      return headers;
  }


  public boolean handleMessage(SOAPMessageContext smc) {
    Boolean outboundProperty = (Boolean)      smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
    SOAPMessage message = smc.getMessage();

    
    if (outboundProperty) {
      try {
        SOAPPart soapPart = message.getSOAPPart();

        SOAPEnvelope envelope = smc.getMessage().getSOAPPart().getEnvelope();
      
        SOAPHeader header2 = envelope.addHeader();
        
        Source source = soapPart.getContent();

        Node root = null;
        Document doc = null;
        if (source instanceof DOMSource) {
          root = ((DOMSource) source).getNode();
        }
        else if (source instanceof SAXSource) {
          InputSource inSource = ((SAXSource) source).getInputSource();
          DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
          dbf.setNamespaceAware(true);
          DocumentBuilder db = null;

          db = dbf.newDocumentBuilder();

          doc = db.parse(inSource);
          root = (Node) doc.getDocumentElement();
        }    
        
        
              
        org.apache.wss4j.dom.message.WSSecSignature builderSig = new WSSecSignature();

        builderSig.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
               
        org.apache.wss4j.dom.message.WSSecHeader  secHeader = new WSSecHeader();
      
        secHeader.insertSecurityHeader(header2.getOwnerDocument());        

        Properties config = new Properties();
        config.load(new FileInputStream(“merlin.properties”)) ;
        Crypto crypto = CryptoFactory.getInstance(config);
        //dobbiamo capire perche la seguente serve, invece di prendere dal properties
        builderSig.setUserInfo(“<Nome Alias>”,”<Password>”);
        builderSig.setUseSingleCertificate(true);
        secHeader.setMustUnderstand(false);
        secHeader.getSecurityHeader().removeAttribute(“S:mustUnderstand”);

        builderSig.appendBSTElementToHeader(secHeader);    
        
        builderSig.build((Document)root, crypto, secHeader);

        printNode((Document)root);
               
      }
      catch (Exception ex) {
        ex.printStackTrace();
        System.exit(-1);
      } 
    }

    return true;
  }


  public boolean handleFault(SOAPMessageContext smc) {
    // addDigitalSignature(smc);
    return true;
  }

  // nothing to clean up
  public void close(MessageContext messageContext) {
  }

}

Di seguito il file di merlin.properties:

org.apache.wss4j.crypto.provider=org.apache.wss4j.common.crypto.Merlin
org.apache.wss4j.crypto.merlin.keystore.type=jks
org.apache.wss4j.crypto.merlin.keystore.password=<Password>
org.apache.wss4j.crypto.merlin.keystore.alias=<Nome Alias>
org.apache.wss4j.crypto.merlin.keystore.file=<Nome File>.jks

l xml prodotto avrà un header così composto:

<soapenv:Header>
<wsse:Security
xmlns:wsse=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd”
xmlns:wsu=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd”>
<wsse:BinarySecurityToken
EncodingType=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary”
ValueType=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3″
wsu:Id=”X509-C672A11E5F8017AFA114337688056892″>MIIDWjCCAkICCQCzH8uW6SulfzANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTESMBAGA1UECAwJS3Jvbm9iZXJnMQ4wDAYDVQQHDAVWYXhqbzERMA8GA1UECgwIR1RFQ0ggRzIxDjAMBgNVBAsMBUlUIERDMRkwFwYDVQQDDBBzdGFnZS1zcG4tZ21zLTAyMB4XDTExMTIxNTE1MDkyMVoXDTIxMTIxMjE1MDkyMVowbzELMAkGA1UEBhMCU0UxEjAQBgNVBAgMCUtyb25vYmVyZzEOMAwGA1UEBwwFVmF4am8xETAPBgNVBAoMCEdURUNIIEcyMQ4wDAYDVQQLDAVJVCBEQzEZMBcGA1UEAwwQc3RhZ2Utc3BuLWdtcy0wMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM5qyhAUFE4lY8rLfGqT1ZjhC4DGTCt8++eBK9xN+Li2cGbqHJBghl1U/6LgHR8/KDYDf0dWKXp89eVIYDpxRhIJgdnFnRbk2/I7Vbq67pyTSkk6DgdyyS55EhKr8Zzb8Eh9dTJsUyWLR9FVEfxHP19ghtW6swLcrH2e+Ktd0OvR0GcOEnalx1VvGLLftyT98ppnhg6YGoyA+uQkri/82COyzbkCyRtbtXB4jq4vEMgv9dTv1l6IXQpSXRncZ3t8SGOL9m6SoHjERsSrhnS4tq6ZffkgBjgfJa2oT4qWO8KeF3yqA8Bmwyzv+v2Ow5mfj6VXcLKzUA+MG4hQ7uZ8SCkCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAbnRcqaQZXxYSn8XEzqmA5L4+ESzhugaiyMWb0n0sklC3AJOufw4gCeK++3GLhqYmhHGmt0T0P3nrcRY6w8SkPsM/Zo0tKdA+W3SrEhDxOi/nhxJoosVcxmk2Qzg9zlKrBMbCic+5OBhkqpUMXTQcl4eOgfIAEtXt8rcaARMLcFx6EWjGc37tejE3nyjtjbGYgLV0RqEsTKz/+qkRx3DZZt441ewH32p+wM6GEexYlVa9lhPi53gB5uxjXzuNGQqqacfI8da+e2JGKavb44DCGraRvUKMxGrO6uGOHoZOvxYXw8J9FVrZ4pr5D3ec7WmNPfgWMkJKjMfM5F2gh8jnkA==</wsse:BinarySecurityToken>
<ds:Signature Id=”SIG-C672A11E5F8017AFA114337688058496″
xmlns:ds=”http://www.w3.org/2000/09/xmldsig#”>
<ds:SignedInfo>
<ds:CanonicalizationMethod
Algorithm=”http://www.w3.org/2001/10/xml-exc-c14n#”>
<ec:InclusiveNamespaces PrefixList=”soapenv ver”
xmlns:ec=”http://www.w3.org/2001/10/xml-exc-c14n#” />
</ds:CanonicalizationMethod>
<ds:SignatureMethod Algorithm=”http://www.w3.org/2000/09/xmldsig#rsa-sha1″ />
<ds:Reference URI=”#id-C672A11E5F8017AFA114337688058355″>
<ds:Transforms>
<ds:Transform Algorithm=”http://www.w3.org/2001/10/xml-exc-c14n#”>
<ec:InclusiveNamespaces PrefixList=”ver”
xmlns:ec=”http://www.w3.org/2001/10/xml-exc-c14n#” />
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm=”http://www.w3.org/2000/09/xmldsig#sha1″ />
<ds:DigestValue>ZrNB9LZb2Eu9pr0rWKg1V2p5ehc=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>GVD3r4yb38OtFPb4PgnnTpOfl60VymGr18/pAsn5hrAZUUMcuCuIPLwV+0cfIoiCTSbRohvEJojW
IXAepaIf/OqfZSsBipHTe2ExFCA36uhnwUO0LC13k+DyvpUmOn2y1g0BIg/RZkwqRy+JktThIAsq
VgTa1AYyQeKY79GG2Pcla+X7iufj2Q9BBidQkK+czNsBSUW8LdSJdq3/+4QJZscODR9c+ybOG1yO
6EyLRU36Tnw3kA2ftzve+hCtxVHeQSh+LcrD1DI4L0uwrhlpwE9ai2mOrSBNLa2q1k1TmnRzAsgv
EqdCkPImL9pySVKPB/uM0sL37Cblfn0Y9JXlkQ==
</ds:SignatureValue>
<ds:KeyInfo Id=”KI-C672A11E5F8017AFA114337688057903″>
<wsse:SecurityTokenReference wsu:Id=”STR-C672A11E5F8017AFA114337688058084″>
<wsse:Reference URI=”#X509-C672A11E5F8017AFA114337688056892″
ValueType=”http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3″ />
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
<wsu:Timestamp wsu:Id=”TS-C672A11E5F8017AFA114337688053671″>
<wsu:Created>2015-06-08T13:06:45Z</wsu:Created>
<wsu:Expires>2015-06-08T13:06:50Z</wsu:Expires>
</wsu:Timestamp>
</wsse:Security>
</soapenv:Header>

Appunti Crittografia

Problema: Bob e Alice si devono scambiare messaggio in modo che anche se viene intercettato nessuno lo possa decriptare ma lo possono leggere solo
i destinatari.
Possibile soluzione: Entrambi avranno una chiave Pubblica,che conoscono tutti, e una chiave privata, personale e segreta.

– Un messaggio cifrato con la chiave PUBBLICA di bob puo essere aperto solo dalla chiave PRIVATA di Bob. Quindi lo puo leggere solo lui. Il problema è che chiunque puo usare la chiave pubblica di Bob per cifrare quindi non sono sicuro che l abbia spedito Alice (Autenticita non rispettata)

– Un messaggio cifrato con la chiave PRIVATA di bob puo essere  aperto solo dalla chiave PUBBLICA di Bob. Sono sicuro che il messaggio è stato mandato da Bob. Il problema è che chiunque abbia la chiave pubblica di Bob può leggere il messaggio(confidenzialità non rispettata)

– Un messaggio  cifrato con la chiave privata si dice “FIRMATO

Firma digitale di un documento
tramite  una funzione  hash (pubblica) si ricava l’impronta digitale del documento, detta anche message digest, ossia un file di dimensioni relativamente piccole (160 bit) che  contiene una sorta di codice di controllo relativo al documento stesso.
La funzione hash è fatta in modo da rendere minima la probabilità che  da testi diversi si possa ottenere il medesimo valore dell’impronta, inoltre, è one-way, a senso unico, questo significa che dall’impronta è  impossibile ottenere nuovamente il testo originario ovvero essa è non invertibile.
Dopodiché si utilizza la propria chiave privata per cifrare  l’impronta digitale: il risultato di questa codifica è la firma.  A questo punto la firma viene allegata al documento.Chiunque può verificare l’autenticità di un documento: per farlo, decifra la firma del documento con la chiave pubblica del mittente, ottenendo l’impronta digitale del documento, e quindi confronta quest’ultima con quella che si ottiene applicando la funzione hash al documento ricevuto;   se le due impronte sono uguali, l’autenticità e l’integrità del documento sono garantite. Quindi quando qualcuno firma un documento garantisce che tutto quello scritto la dentro è vero. Il ricevente a modo di verificare che il contenuto non sia stato modificato durante il tragitto.

Crittografia a chiave pubblica 
 Il mittente codifica due volte l’informazione:
 • con la propria chiave privata
 • con la chiave pubblica del destinatario
 Il destinatario deve effettuare una doppia decodifica per leggere l’informazione:
 • con la propria chiave privata
 • con la chiave pubblica del mittente
 In pratica, per motivi prestazionali, il client e il server usano questa tecnica per scambiarsi
 una chiave simmetrica in modo sicuro e poi passano a un algoritmo di crittografia tradizionale

– Per evitare la necessità di scambiare in anticipo in modo sicuro le chiavi pubbliche,  si usano certificati. Un certificato contiene una chiave pubblica autenticata mediante la firma digitale di una Certification Authority (CA).  Chi riceve il certificato può verificare direttamente l’autenticità della chiave pubblica usando la  chiave pubblica della CA (che deve essere nota).

-La maggior parte dei certificati comunemente utilizzati si basa sullo standard X.509 v3.

 – il certificato quindi è la chiave pubblica di tizio, garantisce per questo chi ha emesso il certificato ossia la CA, firmandolo con la sua chiave privata

– In genere i certificati contengono le informazioni seguenti:

  • il valore della chiave pubblica del soggetto
  • informazioni di identificazione del soggetto, quali il nome e l’indirizzo di posta elettronica
  • il periodo di validità (il periodo nel quale il certificato è considerato valido)
  • informazioni di identificazione dell’autorità di certificazione

-I certificati (quindi le chiavi pubbliche)ritenuti “fidati” sono memorizzati in un truststore.

– Nel keystore sono memorizzate la nostra chiave pubblica e private

-il truststore ha lo stesso identico formato del keystore ma ha una funzione diversa. Nel keystore ci sono la chiave privata e un certificato. Nel truststore c è il certificato.
Funziona il tutto cosi:
il server preleva il suo certificato dal suo keystore e lo spedisce al client. Il client
verifica che il certificato deve appartenere al server. Ossia lo deve avere nel suo truststore.
Quindi nel truststore vengono memorizzati i certificati ritenuti affidabili.
In generale tutti i client SSL devono avere un truststore. Se il server SSL richiede anche
l’autenticazione del client allora deve avere anche lui un trustore.
Riassumento allora abbiamo che il keystore serve per fornire le credenziali (chiave privata e chiave pubblica) mentre il truststore per verificare la chiave pubblica (o certificato). Spesso il keystore e il keytrust sono nello stesso file

– Il keystore puo contenere  coppie chiavi privata-certificato. Ogni coppia puo essere associata ad un alias.

– in java, in pratica, non si fa differenza tra trustore e keystore, si memorizza tutto nel keystore

-SSL supporta sia l’autenticazione lato server che quella lato client; nel primo caso, il più comune, il client controlla l’identità del server verificando che il certificato personale inviato dal server sia firmato da una CA che riconosce; per fare ciò deve disporre di un certificato  emesso dalla CA che ha firmato la chiave pubblica del server.Nel caso di autenticazione lato client invece, è il server che controlla l’identità del client verificando che il certificato inviato da quest’ultimo sia firmato da una CA riconosciuta. Pertanto nell’autenticazione lato server, il client deve possedere solo il certificato della CA del server, mentre nell’autenticazione lato client deve possedere, oltre al certificato  della CA del server, anche il suo certificato personale da inviare al server.

– Keystore e truststore sono gestiti tramite l’utility keytool del JDK.

Comandi importare e visualizzare certificati
importa i certificati
keytool -import -alias <NOME ALIAS> -file <NOME FILE CERTIFICATO.CER> -keystore <NOME KEYSTORE> -storepass <PASSWORD KEYSTORE>
la password dei keystore in genere è changeit. Si puo anche creare un keystore personale e usare quello.
visualizza i certificati
keytool –list -v -keystore <NOME KEYSTORE>

– keystore di sistema:
              $JAVA_HOME/lib/security/cacerts
 Contiene i certificati delle CA riconosciute

-Keystore utente:
               $HOME/.keystore
 Contiene le chiavi dell’utente e quelle che l’utente riconosce

-mostra il contenuto di un certificato
openssl x509 -inform pem -in wild.ordenacionjuego.gob.es.cer  -text

– file cer e file pem sono la stessa cosa

-Struttura di un certificato X.509 :

Certificate  ::=  SEQUENCE  {
    tbsCertificate       TBSCertificate,
    signatureAlgorithm   AlgorithmIdentifier,
    signatureValue       BIT STRING  }

TBSCertificate  ::=  SEQUENCE  {
    version         [0]  EXPLICIT Version DEFAULT v1,
    serialNumber         CertificateSerialNumber,
    signature            AlgorithmIdentifier,
    issuer               Name,
    validity             Validity,
    subject              Name,
    subjectPublicKeyInfo SubjectPublicKeyInfo,
    issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
                         — If present, version MUST be v2 or v3
    subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
                         — If present, version MUST be v2 or v3
    extensions      [3]  EXPLICIT Extensions OPTIONAL
                         — If present, version MUST be v3
    }


-Un certificato PEM può essere letto con un semplice editor di testo e a al suo interno ha seguenti stringhe:
—–BEGIN CERTIFICATE—–
MIIB2zCCAUSgAwIBAwIBADANBgkqhkiG9w0BAQQFADAYMRYwFAYDVQQDEw1OZXRn

—–END CERTIFICATE—–

– si puo avere anche una  private key in PEM format, in questo caso ci potrebbe essere la stringa:
-BEGIN RSA PRIVATE KEY—–