Java 7, HttpClient e il debole algoritmo di firma MD2: Certificates does not conform to algorithm constraints
L’algoritmo di firma RSA-MD2 è ritenuto debole, e viene sconsigliato. Questo è il motivo per cui l’installazione base del jre di Java 7 lo disabilita di default. Questa impostazione è nel file
java.security |
che si trova nella cartella JRE_HOME/lib/security
nella riga
jdk.certpath.disabledAlgorithms=MD2 |
Ma se ci si deve collegare ad un server che espone un certificato firmato in quel modo, si possono avere dei problemi. Ecco la mia storia:
Utilizzando la libreria HttpClient 4.1.2 di Apache, mi sono imbattuto in questa situazione: il codice che esegue una Post sotto ssl funziona se lanciato all’interno dell’ambiente di sviluppo (Eclipse nella fattispecie), ma restituisce un l’errore:
peer not authenticated |
se lanciato da riga di comando dal runnable jar generato.
Il codice è il seguente:
HttpClient httpclient = new DefaultHttpClient(); // creo un TrustManager per considerare tutti i certificati validi, anche se non sono installati sulla macchina X509TrustManager tm = new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted( java.security.cert.X509Certificate[] certs, String authType) { } public void checkServerTrusted( java.security.cert.X509Certificate[] certs, String authType) { } }; try { // Creo il contesto SSL utilizzando i trust manager creati SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, new TrustManager[]{tm}, null); // Creo la connessione https SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); ClientConnectionManager ccm = httpclient.getConnectionManager(); SchemeRegistry sr = ccm.getSchemeRegistry(); sr.register(new Scheme("https", 443, ssf)); httpclient = new DefaultHttpClient(ccm, httpclient.getParams()); HttpPost post = new HttpPost(properties.getXpayAPIurl()); ... String xml = "..." // Un xml di cui fare il Post StringEntity se = new StringEntity(xml); se.setContentType("application/xml"); post.setEntity(se); HttpResponse response = httpclient.execute(post); HttpEntity entity = response.getEntity(); if (entity != null) { repres.setXml(EntityUtils.toString(entity)); } ... |
Per capire il problema ho abilitato il debug ssl a console, impostando le proprietà:
System.setProperty("javax.net.ssl.debug", "all"); System.setProperty("javax.net.debug", "all"); |
L’output del debug ssl termina in questo modo:
main, handling exception: javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Certificates does not conform to algorithm constraints main, IOException in getSession(): javax.net.ssl.SSLHandshakeException: java.security.cert.CertificateException: Certificates does not conform to algorithm constraints |
Questo codice funziona da Eclipse perchè Eclipse utilizza un jre (il 6) diverso da quello utilizzato invece dalla riga di comando, che è invece il 7. Commentando la riga indicata nel file indicato, il problema scompare e il cliente considera valido il certificato firmato con questo algoritmo.
Leave a Reply