Apache HttpClient su Android produzione CertPathValidatorException (IssuerName! = SubjectName)
-
29-09-2019 - |
Domanda
Sto sviluppando un'applicazione Android per l'accesso un po 'di battle.net ( https://eu.battle.net ) dati di account (per World of Warcraft) e sto usando il org.apache.http.client.HttpClient
di farlo.
Questo è il codice che sto usando:
public static final String USER_AGENT = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 (.NET CLR 3.5.30729)";
public static class MyHttpClient extends DefaultHttpClient {
final Context context;
public MyHttpClient(Context context) {
super();
this.context = context;
}
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// Register for port 443 our SSLSocketFactory with our keystore
// to the ConnectionManager
registry.register(new Scheme("https", newSslSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}
private SSLSocketFactory newSslSocketFactory() {
try {
// Get an instance of the Bouncy Castle KeyStore format
KeyStore trusted = KeyStore.getInstance("BKS");
// Get the raw resource, which contains the keystore with
// your trusted certificates (root and any intermediate certs)
InputStream in = context.getResources().openRawResource(R.raw.battlenetkeystore);
try {
// Initialize the keystore with the provided trusted certificates
// Also provide the password of the keystore
trusted.load(in, "mysecret".toCharArray());
} finally {
in.close();
}
// Pass the keystore to the SSLSocketFactory. The factory is responsible
// for the verification of the server certificate.
SSLSocketFactory sf = new SSLSocketFactory(trusted);
// Hostname verification from certificate
// http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506
sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
return sf;
} catch (Exception e) {
throw new AssertionError(e);
}
}
}
private static void maybeCreateHttpClient(Context context) {
if (mHttpClient == null) {
mHttpClient = new MyHttpClient(context);
final HttpParams params = mHttpClient.getParams();
HttpConnectionParams.setConnectionTimeout(params, REGISTRATION_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, REGISTRATION_TIMEOUT);
ConnManagerParams.setTimeout(params, REGISTRATION_TIMEOUT);
Log.d(TAG, LEAVE + "maybeCreateHttpClient()");
}
}
public static boolean authenticate(String username, String password, Handler handler,
final Context context) {
final HttpResponse resp;
final ArrayList<NameValuePair> params = new ArrayList<NameValuePair>();
params.add(new BasicNameValuePair(PARAM_USERNAME, username));
params.add(new BasicNameValuePair(PARAM_PASSWORD, password));
HttpEntity entity = null;
try {
entity = new UrlEncodedFormEntity(params);
} catch (final UnsupportedEncodingException e) {
// this should never happen.
throw new AssertionError(e);
}
final HttpPost post = new HttpPost(THE_URL);
post.addHeader(entity.getContentType());
post.addHeader("User-Agent", USER_AGENT);
post.setEntity(entity);
maybeCreateHttpClient(context);
if (mHttpClient == null) {
return false;
}
try {
resp = mHttpClient.execute(post);
} catch (final IOException e) {
Log.e(TAG, "IOException while authenticating", e);
return false;
} finally {
}
}
L'archivio chiavi viene recuperato (da OpenSSL) in questo modo:
openssl s_client -connect eu.battle.net:443 -showcerts
Ho confrontato i certificati che il comando ha prodotto ( http://vipsaran.webs.com/openssl_output.txt ) con quelli che ho esportato da Firefox ( http://vipsaran.webs.com/Firefox_output.zip ) e sono gli stessi.
Seguendo consigli su questo blog , ho installato il codice precedente e importati CERT (intermedi radice e) per un keystore (battlenetkeystore.bks) che viene utilizzato per HttpClient.
Questo sono i comandi che ho usato per l'importazione i CERT per l'archivio chiavi:
keytool -importcert -v -file ~/lib/ThawteSSLCA.crt -alias thawtesslca -keystore ~/lib/battlenetkeystore.bks -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath ~/lib/bcprov-jdk16-145.jar -storetype BKS -storepass mysecret -keypass mysecret -keyalg "RSA" -sigalg "SHA1withRSA"
keytool -importcert -v -file ~/lib/thawtePrimaryRootCA.crt -alias thawteprimaryrootca -keystore ~/lib/battlenetkeystore.bks -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath ~/lib/bcprov-jdk16-145.jar -storetype BKS -storepass mysecret -keypass mysecret -keyalg "RSA" -sigalg "SHA1withRSA"
Btw. Ho anche provato keytool -import
senza il -keyalg "RSA" -sigalg "SHA1withRSA"
, ma senza alcun cambiamento.
Il problema è che sto ottenendo questo errore:
javax.net.ssl.SSLException: Not trusted server certificate
at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:371)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:92)
at org.apache.http.conn.ssl.SSLSocketFactory.createSocket(SSLSocketFactory.java:381)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:164)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)
at org.homedns.saran.android.wowcalendarsync.network.NetworkUtilities.authenticateWithPass(NetworkUtilities.java:346)
at org.homedns.saran.android.wowcalendarsync.network.NetworkUtilities$1.run(NetworkUtilities.java:166)
at org.homedns.saran.android.wowcalendarsync.network.NetworkUtilities$5.run(NetworkUtilities.java:278)
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: IssuerName(CN=thawte Primary Root CA, OU="(c) 2006 thawte, Inc. - For authorized use only", OU=Certification Services Division, O="thawte, Inc.", C=US) does not match SubjectName(CN=Thawte SSL CA, O="Thawte, Inc.", C=US) of signing certificate
at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:168)
at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:366)
... 12 more
Caused by: java.security.cert.CertPathValidatorException: IssuerName(CN=thawte Primary Root CA, OU="(c) 2006 thawte, Inc. - For authorized use only", OU=Certification Services Division, O="thawte, Inc.", C=US) does not match SubjectName(CN=Thawte SSL CA, O="Thawte, Inc.", C=US) of signing certificate
at org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi.engineValidate(PKIXCertPathValidatorSpi.java:373)
at java.security.cert.CertPathValidator.validate(CertPathValidator.java:202)
at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:164)
... 13 more
e non riesco a capire un modo per risolverlo. Provato ad importare i CERT nell'archivio chiavi in ??ordine diverso, Aso. ma niente ha funzionato.
help (e vi prego di concentrarsi sulle soluzioni basate su Apache del Android HttpClient solo ).
Soluzione
mi aspetto che tu hai la tua propria soluzione per ora, ma se non:
Grazie alla combinazione di intuizioni da
- Il blog di Antoine Hauck
- http://blog.synyx.de/2010/06/ Android-e-self-signed-SSL-certificati /
- la risposta eccellente da BDC sopra
- codice sorgente facilmente su google per "EasySSLSocketFactory" e "EasyX509TrustManager" - (! Prima segreteria volta) fornirebbe un collegamento se non fossi impedito
sono riuscito a ottenere una connessione sicura a https://eu.battle.net/login/en/login .xml con solo le seguenti classi. Si noti che non v'è alcuna necessità di costruire un archivio di chiavi in ??quanto la CA principale è considerato attendibile da Android -. Il problema è semplicemente che i certs vengono restituiti nell'ordine sbagliato
(Disclaimer:. Forse non spendere qualsiasi momento la pulizia del codice fino però)
EasyX509TrustManager:
package com.trustit.trustme;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class EasyX509TrustManager implements X509TrustManager
{
private X509TrustManager standardTrustManager = null;
/**
* Constructor for EasyX509TrustManager.
*/
public EasyX509TrustManager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException
{
super();
TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
factory.init(keystore);
TrustManager[] trustmanagers = factory.getTrustManagers();
if (trustmanagers.length == 0)
{
throw new NoSuchAlgorithmException("no trust manager found");
}
this.standardTrustManager = (X509TrustManager) trustmanagers[0];
}
/**
* @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],String authType)
*/
public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException
{
standardTrustManager.checkClientTrusted(certificates, authType);
}
/**
* @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],String authType)
*/
public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException
{
// Clean up the certificates chain and build a new one.
// Theoretically, we shouldn't have to do this, but various web servers
// in practice are mis-configured to have out-of-order certificates or
// expired self-issued root certificate.
int chainLength = certificates.length;
if (certificates.length > 1)
{
// 1. we clean the received certificates chain.
// We start from the end-entity certificate, tracing down by matching
// the "issuer" field and "subject" field until we can't continue.
// This helps when the certificates are out of order or
// some certificates are not related to the site.
int currIndex;
for (currIndex = 0; currIndex < certificates.length; ++currIndex)
{
boolean foundNext = false;
for (int nextIndex = currIndex + 1;
nextIndex < certificates.length;
++nextIndex)
{
if (certificates[currIndex].getIssuerDN().equals(
certificates[nextIndex].getSubjectDN()))
{
foundNext = true;
// Exchange certificates so that 0 through currIndex + 1 are in proper order
if (nextIndex != currIndex + 1)
{
X509Certificate tempCertificate = certificates[nextIndex];
certificates[nextIndex] = certificates[currIndex + 1];
certificates[currIndex + 1] = tempCertificate;
}
break;
}
}
if (!foundNext) break;
}
// 2. we exam if the last traced certificate is self issued and it is expired.
// If so, we drop it and pass the rest to checkServerTrusted(), hoping we might
// have a similar but unexpired trusted root.
chainLength = currIndex + 1;
X509Certificate lastCertificate = certificates[chainLength - 1];
Date now = new Date();
if (lastCertificate.getSubjectDN().equals(lastCertificate.getIssuerDN())
&& now.after(lastCertificate.getNotAfter()))
{
--chainLength;
}
}
standardTrustManager.checkServerTrusted(certificates, authType);
}
/**
* @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
*/
public X509Certificate[] getAcceptedIssuers()
{
return this.standardTrustManager.getAcceptedIssuers();
}
}
EasySSLSocketFactory
package com.trustit.trustme;
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.LayeredSocketFactory;
import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
public class EasySSLSocketFactory implements SocketFactory, LayeredSocketFactory
{
private SSLContext sslcontext = null;
private static SSLContext createEasySSLContext() throws IOException
{
try
{
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[] { new EasyX509TrustManager(null) }, null);
return context;
}
catch (Exception e)
{
throw new IOException(e.getMessage());
}
}
private SSLContext getSSLContext() throws IOException
{
if (this.sslcontext == null)
{
this.sslcontext = createEasySSLContext();
}
return this.sslcontext;
}
/**
* @see org.apache.http.conn.scheme.SocketFactory#connectSocket(java.net.Socket, java.lang.String, int,
* java.net.InetAddress, int, org.apache.http.params.HttpParams)
*/
public Socket connectSocket(Socket sock,
String host,
int port,
InetAddress localAddress,
int localPort,
HttpParams params)
throws IOException, UnknownHostException, ConnectTimeoutException
{
int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
int soTimeout = HttpConnectionParams.getSoTimeout(params);
InetSocketAddress remoteAddress = new InetSocketAddress(host, port);
SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket());
if ((localAddress != null) || (localPort > 0))
{
// we need to bind explicitly
if (localPort < 0)
{
localPort = 0; // indicates "any"
}
InetSocketAddress isa = new InetSocketAddress(localAddress, localPort);
sslsock.bind(isa);
}
sslsock.connect(remoteAddress, connTimeout);
sslsock.setSoTimeout(soTimeout);
return sslsock;
}
/**
* @see org.apache.http.conn.scheme.SocketFactory#createSocket()
*/
public Socket createSocket() throws IOException {
return getSSLContext().getSocketFactory().createSocket();
}
/**
* @see org.apache.http.conn.scheme.SocketFactory#isSecure(java.net.Socket)
*/
public boolean isSecure(Socket socket) throws IllegalArgumentException {
return true;
}
/**
* @see org.apache.http.conn.scheme.LayeredSocketFactory#createSocket(java.net.Socket, java.lang.String, int,
* boolean)
*/
public Socket createSocket(Socket socket,
String host,
int port,
boolean autoClose) throws IOException,
UnknownHostException
{
return getSSLContext().getSocketFactory().createSocket(socket, host, port, autoClose);
}
// -------------------------------------------------------------------
// javadoc in org.apache.http.conn.scheme.SocketFactory says :
// Both Object.equals() and Object.hashCode() must be overridden
// for the correct operation of some connection managers
// -------------------------------------------------------------------
public boolean equals(Object obj) {
return ((obj != null) && obj.getClass().equals(EasySSLSocketFactory.class));
}
public int hashCode() {
return EasySSLSocketFactory.class.hashCode();
}
}
MyHttpClient
package com.trustit.trustme;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.SingleClientConnManager;
import org.apache.http.params.HttpParams;
import android.content.Context;
public class MyHttpClient extends DefaultHttpClient
{
final Context context;
public MyHttpClient(HttpParams hparms, Context context)
{
super(hparms);
this.context = context;
}
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
// Register for port 443 our SSLSocketFactory with our keystore
// to the ConnectionManager
registry.register(new Scheme("https", new EasySSLSocketFactory(), 443));
//http://blog.synyx.de/2010/06/android-and-self-signed-ssl-certificates/
return new SingleClientConnManager(getParams(), registry);
}
}
TrustMe (attività)
package com.trustit.trustme;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class TrustMe extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView tv = (TextView)findViewById(R.id.tv1);
HttpParams httpParameters = new BasicHttpParams();
// Set the timeout in milliseconds until a connection is established.
int timeoutConnection = 10000;
HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);
// Set the default socket timeout (SO_TIMEOUT)
// in milliseconds which is the timeout for waiting for data.
int timeoutSocket = 10000;
HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket);
// Instantiate the custom HttpClient
HttpClient client = new MyHttpClient(httpParameters,
getApplicationContext());
HttpGet request = new HttpGet("https://eu.battle.net/login/en/login.xml");
BufferedReader in = null;
try
{
HttpResponse response = client.execute(request);
in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer sb = new StringBuffer("");
String line = "";
String NL = System.getProperty("line.separator");
while ((line = in.readLine()) != null)
{
sb.append(line + NL);
}
in.close();
String page = sb.toString();
//System.out.println(page);
tv.setText(page);
}
catch (ClientProtocolException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
if (in != null)
{
try
{
in.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
}
}
Altri suggerimenti
Guardando "OpenSSL s_client -connect eu.battle.net:443", vedo la seguente catena cert:
Certificate chain
0 s:/C=US/ST=California/L=Irvine/O=Blizzard Entertainment, Inc./CN=*.battle.net
i:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
1 s:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
i:/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting cc/OU=Certification Services Division/CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com
2 s:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
Si noti che è fuori uso. l'emittente di cert "n" nella catena deve corrispondere al tema del CERT "n + 1". L'emittente dell'ultimo CERT dovrebbe essere essere auto firmato (soggetto == emittente) e tecnicamente non incluso.
La catena corretta sarebbe essere ordinato in questo modo:
Certificate chain
0 s:/C=US/ST=California/L=Irvine/O=Blizzard Entertainment, Inc./CN=*.battle.net
i:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
1 s:/C=US/O=Thawte, Inc./CN=Thawte SSL CA
i:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
2 s:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
i:/C=ZA/ST=Western Cape/L=Cape Town/O=Thawte Consulting cc/OU=Certification Services Division/CN=Thawte Premium Server CA/emailAddress=premium-server@thawte.com
I piviali del browser Android con fuori la catena dell'ordine da avere la sua android.net.http.CertificateChainValidator codice di riordino della catena del CERT prima di passarlo per la convalida.
136 // Clean up the certificates chain and build a new one.
137 // Theoretically, we shouldn't have to do this, but various web servers
138 // in practice are mis-configured to have out-of-order certificates or
139 // expired self-issued root certificate.
140 int chainLength = serverCertificates.length;
141 if (serverCertificates.length > 1) {
142 // 1. we clean the received certificates chain.
143 // We start from the end-entity certificate, tracing down by matching
144 // the "issuer" field and "subject" field until we can't continue.
145 // This helps when the certificates are out of order or
146 // some certificates are not related to the site.
147 int currIndex;
148 for (currIndex = 0; currIndex < serverCertificates.length; ++currIndex) {
149 boolean foundNext = false;
150 for (int nextIndex = currIndex + 1;
151 nextIndex < serverCertificates.length;
152 ++nextIndex) {
153 if (serverCertificates[currIndex].getIssuerDN().equals(
154 serverCertificates[nextIndex].getSubjectDN())) {
155 foundNext = true;
156 // Exchange certificates so that 0 through currIndex + 1 are in proper order
157 if (nextIndex != currIndex + 1) {
158 X509Certificate tempCertificate = serverCertificates[nextIndex];
159 serverCertificates[nextIndex] = serverCertificates[currIndex + 1];
160 serverCertificates[currIndex + 1] = tempCertificate;
161 }
162 break;
163 }
164 }
165 if (!foundNext) break;
166 }
167
168 // 2. we exam if the last traced certificate is self issued and it is expired.
169 // If so, we drop it and pass the rest to checkServerTrusted(), hoping we might
170 // have a similar but unexpired trusted root.
171 chainLength = currIndex + 1;
172 X509Certificate lastCertificate = serverCertificates[chainLength - 1];
173 Date now = new Date();
174 if (lastCertificate.getSubjectDN().equals(lastCertificate.getIssuerDN())
175 && now.after(lastCertificate.getNotAfter())) {
176 --chainLength;
177 }
178 }
Per far fronte a questo nella vostra app, si vuole creare il proprio javax.net.ssl.SSLSocketFactory da uno SSLContext che è stato inizializzato con un X509TrustManager che riordina la catena prima di chiamare il TrustManagerFactory predefinito fornito TrustManager.
Ho non recentemente esaminato il codice di Apache HTTP del client per vedere come fornire la vostra abitudine javax.net.ssl.SSLSocketFactory al loro involucro SSLSocketFactory, ma dovrebbe essere possibile (o semplicemente non utilizzare Apache HTTP client e basta usare nuovo URL ( "https: // .."). .openConnection (), che consente di specificare il javax.net.ssl.SSLSocketFactory personalizzato sul HttpsURLConnection
Infine, nota che si dovrebbe solo bisogno di importare il self-signed CA principale nel vostro keystore (e solo se non è già in negozio sistema, ma ho appena controllato e questo CA non è presente in froyo). Il CA che si desidera in questo caso ha Oggetto:
/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA
Credo che il problema è risolto in questo momento, ma ho avuto lo stesso e ho anche lottato un po 'di tempo per trovare la soluzione giusta. Forse aiuta qualcuno.
Ho anche usato il codice Antoine blog ma ho cambiato il costruttore utilizzato per la SSLSocketFactory.
uso Così ho
SSLSocketFactory sf = new SSLSocketFactory(certStore, "some_password", trustStore);
Perciò ho creato due archivi di chiavi
KeyStore trustStore = KeyStore.getInstance("BKS");
KeyStore certStore = KeyStore.getInstance("BKS");
InputStream in = context.getResources().openRawResource(R.raw.signature_certstore);
try {
certStore.load(in, "some_password".toCharArray());
} finally {
in.close();
}
in = context.getResources().openRawResource(R.raw.signature_truststore);
try {
trustStore.load(in, "some_password".toCharArray());
} finally {
in.close();
}
Ho creato i magazzini BKS con Portecle . Negli signature_truststore.bks ho importato la radice certificato e nei signature_certstore.bks devi uno d'importazione o di più intermedi.
Il resto del codice è esattamente la stessa di quella dal blog.
Non ho una soluzione per risolvere il percorso. Ma ho una soluzione per ignorare certs. Io uso questo metodo per ignorare auto certs firmati in fase di sviluppo. Vedere se aiuta.
protected final static ClientConnectionManager clientConnectionManager;
protected final static HttpParams params;
// ......
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", new EasySSLSocketFactory(), 443));
params = new BasicHttpParams();
params.setParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, 1);
params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(1));
params.setParameter(HttpProtocolParams.USE_EXPECT_CONTINUE, false);
HttpProtocolParams.setUserAgent(params, "android-client-v1.0");
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setContentCharset(params, "utf8");
clientConnectionManager = new ThreadSafeClientConnManager(params, schemeRegistry);
// and later do this
HttpClient client = new DefaultHttpClient(clientConnectionManager, params);
HttpGet request = new HttpGet(uri);
HttpResponse response = client.execute(request);
questo aiuto maggio: http: // blog .antoine.li / index.php / 2010/10 / android-confidando-SSL-certificati / , do u hanno fiducia certificati da una CA (come versign o Geotrust)? o si sta usando certificato auto firmato ... stavo affrontando problema simile e risolto oggi ...
A proposito, io sono l'autore del blog di cui sopra;) Io cerco di rispondere alla tua domanda qui
.Ho guardato le vostre uscite certificato da Firefox e OpenSSL e ha trovato qualcosa di interessante.
Guarda il certificato CA principale (indice 1) a vostra uscita OpenSSL. Il nome emittente è: Thawte Premium Server CA Il nome del soggetto è: Thawte primaria Root CA I nomi all'oggetto e all'emittente sono diversi. Pertanto, questo certificato non è considerato come il Root CA, perché è stato emesso da un'altra istanza. Pertanto, il provider BouncyCastle sta prendendo in considerazione questo certificato come il CA principale, ma si lamenta perché temi e soggetti sono diversi.
Non ho idea di come si è ottenuto il certificato Root CA "sbagliato". Quando guardo il certificato CA principale in Firefox, il soggetto ed emittente sono gli stessi, come dovrebbe essere.
Cerca di ottenere il diritto di Root CA e riprovare.
Spero che questo aiuti. Saluti e buona fortuna;)
ho finalmente risolto il mio stesso "IssuerName non corrisponde SubjectName" eccezione. Ho seguito lo stesso blog di Antoine e ciò che è descritto qui numerose volte, ed ecco come renderlo finalmente lavoro:
1) Il nostro sito utilizza due certificati di GeoTrust: il CA intermedio viene rilasciato a noi da GeoTrust SSL CA, e la CA principale viene rilasciato a GeoTrust SSL CA da GeoTrust globale di CA;
2) Se si utilizzano solo la radice di CA o di entrambi la radice e le CA intermedie in 1), ottengo l'eccezione mancata corrispondenza, perché Android solo supporti un numero limitato di fiducia CA principale , e GeoTrust globale CA non è nella lista;
3) Nella pagina di supporto di www.geotrust.com, c'è una pagina chiamata GeoTrust Croce Root CA, è sufficiente scaricare, salvarlo a un nome come crossroot.pem, e utilizzare questo comando per generare la chiavi:
C: \ Program Files \ Java \ jdk1.6.0_24 \ bin> keytool -importcert -v -trustcacerts -file c: \ ssl \ crossroot.pem -alias newroot -keystore c: \ ssl \ crossroot.bks dal provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "c: \ downloads \ bcprov-jdk16-145.jar" -storetype BKS -storepass mYsEcret
Fase 2 del blog da Antonie ha un link per scaricare il BouncyCastleProvider;
4) Aggiungere il file di archivio chiavi al progetto Android, e funziona - questo ha un senso perchè reperti ora Android una fonte attendibile Equifax Secure Certificate Authority (vedere l'elenco di cui sopra 1 ) il cui SubjectName GeoTrust globale CA corrisponde radice del nostro sito IssuerName.
5) Il codice nella fase 3 di blog funziona bene, e solo per renderlo più completo, ho copiato il mio codice di prova di seguito:
HttpResponse response = client.execute(get);
HttpEntity entity = response.getEntity();
BufferedReader in = new BufferedReader(new InputStreamReader(entity.getContent()));
String line;
while ((line = in.readLine()) != null)
System.out.println(line);
in.close();
La parte più difficile di questo problema è se emittente root CA non è nella lista di fiducia del Android, dovrete farlo da parte della società che rilascia all'utente i certificati - chiedere loro di fornire un CA principale croce che ha l'emittente radice come una delle CA radice attendibili di Android.