Dans cet article, nous allons voir comment importer un certificat auto-signé dans votre application pour réaliser une connexion SSL sécurisée à l’aide de Bouncy Castle.

Android possède un Keystore contenant toutes les clés publiques certifiées par Google.  Si vous tentez de faire une requête HTTPS depuis votre application sur un site ayant un certificat auto-signé, il y a de fortes chances qu’elle soit refusée. Voici comment ajouter un certificat auto-signé à votre application.

BouncyCastle Provider

Pour commencer, vous devez télécharger BouncyCastle Provider disponible ici (un fichier jar) et le placer dans un dossier que vous saurez retrouver ensuite.

Récupérer les certificats

Depuis un navigateur comme Chrome ou Firefox, rien de plus simple:

  • depuis une page de votre site : clic droit/afficher les informations.
  • Ensuite exportez le certificat au format .cer. Dans le cas où vous avez une chaine de certificat, toute la chaine est nécessaire.

Création du keystore

Ouvrez une fenêtre en ligne de commande. Il faut que vous vous trouviez dans le dossier …/Java/jre/bin pour pouvoir utiliser l’outil keytool. Pour cela, tapez “cd chemin_vers_java/Java/jre/bin”. Tapez ensuite la commande suivante:

keytool -importcert -v -trustcacerts -file "chemin_vers_le_certificat/moncertificat.cer" -alias IntermediateCA -keystore "chemin_nouveau_keystore/myKeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath "chemin_vers_bouncycastle/bcprov-jdk16-146.jar" -storetype BKS -storepass monmotdepasse

Un message doit normalement vous dire “Un certificat a été ajouté au keystore

NOTE : si vous avez une chaine de certificats, commencez par le certificat le plus bas et remontez ensuite vers le certificat racine.

La commande suivante permet de vérifier que le certificat a été ajouté :

keytool -list -keystore " chemin_nouveau_keystore/myKeystore.bks" -provider org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath " chemin_vers_bouncycastle /bcprov-jdk16-145.jar" -storetype BKS -storepass monmotdepasse

NOTE : le mot de passe (storepass) servira lors de chaque ouverture de notre keystore.

Si le certificat a été ajouté, vous aurez un message de ce genre:

IntermediateCA, 22.10.2010, trustedCertEntry, Thumbprint (MD5): 98:0F:C3:F8:39:F7:D8:05:07:02:0D:E3:14:5B:29:43

Vous devez ensuite ajouter le keystore créé dans les ressources du projet, dans le dossier res/raw.

Création d’une classe HTTP personnalisée

Créez ensuite une nouvelle classe nommée “MyHttpClient“. Cette classe dérivera de la classe DefaultHttpClient définie par Android et utilisera le keystore créé précédemment.

public class MyHttpClient extends DefaultHttpClient {
 final Context context;
 public MyHttpClient(Context context) {
  this.context = context;
 }

 @Override
 protected ClientConnectionManager createClientConnectionManager() {
  SchemeRegistry registry = new SchemeRegistry();
  //Pour les requêtes HTTP, on laisse la classe de base s'en occuper.
  registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
  // Les requêtes HTTPS se font sur le port 443. A chaque connexion HTTPS, c’est notre keystore qui sera utilisé.
  registry.register(new Scheme("https", newSslSocketFactory(), 443));
  return new SingleClientConnManager(getParams(), registry);
 }

 private SSLSocketFactory newSslSocketFactory() {
  try {
  // On obtient une instance de notre KeyStore
  trusted = KeyStore.getInstance("BKS");
  InputStream in = context.getResources().openRawResource(R.raw.mykeystore);
   try {
    // Initialisation de notre keystore. On entre le mot de passe (storepass)
    trusted.load(in, "monmotdepasse".toCharArray());
    } finally {
   in.close();
   }

  // Passons le keystore au SSLSocketFactory qui est responsable de la verification du certificat
  SSLSocketFactory sf = new SSLSocketFactory(trusted);
  sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);
  return sf;
  } catch (Exception e) {
   throw new AssertionError(e);
  }
 }
}

On utilise ensuite cette classe comme la classe HTTP de base d’Android:

DefaultHttpClient client = new MyHttpClient(getApplicationContext()); HttpGet get = new HttpGet("https://monsitesecurise.com");

Conclusion

Voilà le tutoriel est terminé, en espérant que vous ayez compris comment ajouter vos propres certificats.

Categories: Tutoriels

14 Responses so far.


  1. psv dit :

    Bonjour,
    J’ai réalisé ce tuto pas à pas.
    Tout fonctionne merveilleusement bien.
    Je tiens à signaler cependant qu’il y a une variable non initialisée dans le code fourni (je crois que c’est la variable “trusted”, de mémoire…)

    J’ai aussi rencontré le problème que le nom de mon certificat ne correspondait pas au site interrogé, c’est une erreur de type :
    javax.net.ssl.SSLException: hostname in certificate didn’t match

    Pour palier à ce problème, il faut modifier une ligne (vous saurez retrouver laquelle) de la façon suivante :
    sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

    C’est assez explicite je crois.

    Merci pour ce tuto, c’est parfait.

  2. Houssam dit :

    Merci infiniment pour ce tuto.

    avec Android,une fois on a l’apk de l’application, on peut extraire toutes les ressources y compris le certificat et puis, on peut aussi avoir le code source de l’application et donc avoir le mot de passe du certificat.
    alors toute personne peut avoir le certificat et son mot de passe et pourra donc créer facilement une autre application qui communique avec le serveur!!

    ceci pose un grand problème de sécurité n’est ce pas ?!!

    • Effectivement c’est possible. Malheureusement c’est le gros problème avec Android et il est difficile de sécuriser davantage

      • Houssam dit :

        Merci Arnaud pour ta réponse.

        je te serai reconnaissant si tu peux m’indiquer d’autres moyens pour sécuriser davantage une application android surtout les échanges entre un client mobile et un serveur web.
        peu importe si c’est difficile, l’essentiel que ça soit pas impossible.

  3. mejdoub khouloud dit :

    Bonjour,
    j’ai un problème dans mon application android ,l’erreur est “No peer certificate”
    Pouvez vous m’explique cette erreur?

  4. BELDA dit :

    Salut , ce code marche pas avec moi , je pense que la classe SSLSocketFactory est absraite du coup cette ligne ” SSLSocketFactory sf = new SSLSocketFactory(trusted); ”
    est une erreur ! merci de votre aide

    • L’erreur vient certainement d’un mauvais import. Ici, l’import doit être import org.apache.http.conn.ssl.SSLSocketFactory;
      Tu as sûrement importé le mauvais package (javax.net.ssl.SSLSocketFactory)

  5. ines dit :

    merci beaucoup
    very useful cet tuto

Leave a Reply


Notifiez-moi des commentaires à venir via email. Vous pouvez aussi vous abonner sans commenter.