Bonjour à tous !
Je travaille actuellement avec des amis sur un petit jeu en ligne, et nous aimerions crypter les messages qui circulent pour éviter les problèmes liés aux sniffers réseau.
Nous nous sommes donc tournés vers SSL, surtout que nous avons un certificat gratuit pour un an grâce à notre hébergement OVH.
Le client et le serveur sont tous deux en Java, et communiquent via des Sockets TCP non-bloquantes (librairie xSocket).
Après moult difficultés, je suis parvenu à importer mon certificat fourni par OVH dans mon keystore. J'ai ensuite codé le serveur minimaliste suivant :
Le handler est dénué d'intérêt, il se contente d'envoyer un "Hello World" à la connexion.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 public class Main { public static String KEYSTORE_PATH = "D:\\Developpement\\Java\\SSLServer\\keystore"; public static void main(String[] args) { SSLContext sslc = getSSLContext(); try { IServer server; if (sslc != null) server = new Server(7777, new Handler(), sslc, true); else server = new Server(7777, new Handler()); // Pas de SSL server.start(); } catch (IOException e) { e.printStackTrace(); } } public static SSLContext getSSLContext() { try { File keystore = new File(KEYSTORE_PATH); char[] passphrase = "monPassword".toCharArray(); KeyStore ks = KeyStore.getInstance("JKS"); ks.load(new FileInputStream(keystore), passphrase); KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509"); kmf.init(ks, passphrase); TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); tmf.init(ks); SSLContext sslContext = SSLContext.getInstance("SSLv3"); sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); return sslContext; } catch (Exception e) { System.out.println("Erreur lors de l'accès au keystore... La connexion ne sera pas sécurisée.\n"); return null; } } }
Le client, de son côté, est également minimaliste :
Lors de mes tests, j'obtiens une exception qui me dit que la validité du certificat n'a pas pu être vérifiée :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 public class Main { public static String SERVER = "www.sitecertifie.com"; public static int PORT = 7777; public static void main(String[] args) { try { Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()); SSLSocket socket = (SSLSocket) SSLSocketFactory.getDefault().createSocket(SERVER, PORT); BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); in.readLine(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
En découlent deux questions :PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
1) Mon certificat étant valide, quelle erreur ai-je commise qui empêche la reconnaissance du certificat ?
2) Dans le cas où je ne parviendrais pas à faire vérifier le certificat par Java, y a-t-il un moyen de le faire accepter par le client sans qu'il ait à bidouiller keytool ? J'ai vu plusieurs messages qui proposaient d'ajouter le certificat du serveur au keystore du client mais vu la manip, c'est impensable pour un déploiement. En dernier recours, y a-t-il une méthode de cryptage plus simple à mettre en place ?
Merci d'avance !
Partager