Je suis en train de travailler sur une application Android qui exige à la fois le client et le serveur d'authentification par certificat. J'ai un SSLClient classe que j'ai créé qui fonctionne à merveille sur de bureau ordinaire Java SE 6. J'ai déménagé dans mon projet Android et j'obtiens l'erreur suivante: "KeyStore JKS mise en œuvre n'est pas trouvé".
J'ai regardé en ligne un peu et on dirait qu'il ya une possibilité que Java fichiers de clés ne sont pas pris en charge sur Android (génial!) mais j'ai le sentiment que c'est bien plus que cela parce que aucun de l'exemple de code que j'ai trouvé ressemble à ce que j'essaie de le faire du tout. Tout ce que j'ai trouvé parle à l'aide d'un client http, plutôt que de raw sockets SSL. J'ai besoin de sockets SSL pour cette application.
Ci-dessous le code de mon SSLClient.java fichier. Il lit le fichier de clés et truststore, crée un socket SSL connexion au serveur, puis exécute une boucle lors de l'attente pour les lignes d'entrée à partir du serveur puis les traite comme ils viennent dans par l'appel d'une méthode dans une classe différente. Je suis très intéressé d'entendre toute personne avec toute l'expérience de faire des sockets SSL sur la plate-forme Android.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.security.AccessControlException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import otherpackege.OtherClass;
import android.content.Context;
import android.util.Log;
public class SSLClient
{
static SSLContext ssl_ctx;
public SSLClient(Context context)
{
try
{
// Setup truststore
KeyStore trustStore = KeyStore.getInstance("BKS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
InputStream trustStoreStream = context.getResources().openRawResource(R.raw.mysrvtruststore);
trustStore.load(trustStoreStream, "testtest".toCharArray());
trustManagerFactory.init(trustStore);
// Setup keystore
KeyStore keyStore = KeyStore.getInstance("BKS");
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
InputStream keyStoreStream = context.getResources().openRawResource(R.raw.clientkeystore);
keyStore.load(keyStoreStream, "testtest".toCharArray());
keyManagerFactory.init(keyStore, "testtest".toCharArray());
Log.d("SSL", "Key " + keyStore.size());
Log.d("SSL", "Trust " + trustStore.size());
// Setup the SSL context to use the truststore and keystore
ssl_ctx = SSLContext.getInstance("TLS");
ssl_ctx.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
Log.d("SSL", "keyManagerFactory " + keyManagerFactory.getKeyManagers().length);
Log.d("SSL", "trustManagerFactory " + trustManagerFactory.getTrustManagers().length);
}
catch (NoSuchAlgorithmException nsae)
{
Log.d("SSL", nsae.getMessage());
}
catch (KeyStoreException kse)
{
Log.d("SSL", kse.getMessage());
}
catch (IOException ioe)
{
Log.d("SSL", ioe.getMessage());
}
catch (CertificateException ce)
{
Log.d("SSL", ce.getMessage());
}
catch (KeyManagementException kme)
{
Log.d("SSL", kme.getMessage());
}
catch(AccessControlException ace)
{
Log.d("SSL", ace.getMessage());
}
catch(UnrecoverableKeyException uke)
{
Log.d("SSL", uke.getMessage());
}
try
{
Handler handler = new Handler();
handler.start();
}
catch (IOException ioException)
{
ioException.printStackTrace();
}
}
}
//class Handler implements Runnable
class Handler extends Thread
{
private SSLSocket socket;
private BufferedReader input;
static public PrintWriter output;
private String serverUrl = "174.61.103.206";
private String serverPort = "6000";
Handler(SSLSocket socket) throws IOException
{
}
Handler() throws IOException
{
}
public void sendMessagameInfoge(String message)
{
Handler.output.println(message);
}
@Override
public void run()
{
String line;
try
{
SSLSocketFactory socketFactory = (SSLSocketFactory) SSLClient.ssl_ctx.getSocketFactory();
socket = (SSLSocket) socketFactory.createSocket(serverUrl, Integer.parseInt(serverPort));
this.input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Handler.output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
Log.d("SSL", "Created the socket, input, and output!!");
do
{
line = input.readLine();
while (line == null)
{
line = input.readLine();
}
// Parse the message and do something with it
// Done in a different class
OtherClass.parseMessageString(line);
}
while ( !line.equals("exit|") );
}
catch (IOException ioe)
{
System.out.println(ioe);
}
finally
{
try
{
input.close();
output.close();
socket.close();
}
catch(IOException ioe)
{
}
finally
{
}
}
}
}
Mise à jour:
Faire quelques bons progrès sur ce problème. Découvert que notre établissement n'est en effet pas pris en charge, ni directement le choix de la SunX509 type. J'ai mis à jour mon code ci-dessus pour tenir compte de ces changements. Je suis toujours avoir un problème avec elle apparemment pas le chargement du fichier de stockage des clés et truststore. Je vais mettre à jour que je figure sur plus.
Update2:
Je faisais mon fichier de clés et truststore chargement d'un fichier dans un bureau de Java façon plutôt que de le corriger Android manière. Les fichiers doivent être placés dans le res/raw dossier et chargé à l'aide de getResources(). Je suis maintenant un nombre de 1 et 1 pour le fichier de clés et truststore taille, ce qui signifie qu'ils sont de chargement. Je suis toujours de s'écraser sur une exception, mais se rapproche! Je vais mettre à jour quand je reçois ce travail.
Update3:
Ressemble tout fonctionne maintenant, à l'exception de mon fichier de clés étant configuré de manière incorrecte. Si je désactive le côté client d'authentification sur le serveur, il se connecte sans problème. Quand je le laisse activé, je reçois un handling exception: javax.net.ssl.SSLHandshakeException: null cert chain
d'erreur. Donc il semble que je ne suis pas la configuration de la chaîne de certificats correctement. J'ai posté une autre question me demandant comment créer un client de magasin de clés dans le BKS format avec le bon certificat de la chaîne d': Comment créer un BKS (BouncyCastle) format Java fichier de clés qui contient un certificat du client de la chaîne d'