Bonjour,

je developpe actuellement une application client/serveur en Java. L'application fonctionne mais maintenant je souhaite introduire un peu de sécurité.

Pour cela, j'ai développé sur le serveur une classe qui permet de generer une paire de clés publique/privée. Ensuite pour transferer la clé publique au client, j'ai écrit une méthode qui permet de sauvegarder la clé publique dans un fichier puis je souhaiterais envoyer ce fichier sous forme de tableau de byte au client.

L'application cliente fonctionne de la manière suivante :

- elle a un thread qui est charger de recevoir un entier du serveur
sur un DataInputStream (cet entier represente le code du message a traiter)

- ensuite suivant l'entier reçu,ce thread appel la méthode adéquat pour traiter le message.



Ainsi, lorsque le serveur envoi le fichier (sous forme de tableau de byte) le client le reçoit bien. Ensuite le thread de reception se remet en attente d'un entier de la part du serveur et c'est ici qu'il y a un probleme. En effet, après la reception du fichier, dès que le thread essaie de lire un entier reçu par le serveur j'ai une exception de type EOFException. J'ai l'impression que le DataInputStream est fermé alors que la méthode "close()" n'est appelée null part

Je vous mets le code ci-dessous :

la classe permettant de generer les cles :

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
 
 
public class CryptageRSA {
 
	private KeyPair paireDeCle;
	private RSAPrivateKey clePrivee;
	private RSAPublicKey clePublic;
	private KeyPairGenerator KeyPairGen;
	private final static int TAILLE_CLE = 2048;
 
 
	public CryptageRSA(){
 
		/* On genere la paire de cles */
		try {
			KeyPairGen = KeyPairGenerator.getInstance("RSA");
 
			KeyPairGen.initialize(TAILLE_CLE, new SecureRandom());
			paireDeCle = KeyPairGen.generateKeyPair();
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		/* on recupere la cle publique et privee */
		clePublic = (RSAPublicKey)paireDeCle.getPublic();
		clePrivee = (RSAPrivateKey)paireDeCle.getPrivate();
 
 
 
 
 
	}
 
	public byte[] crypter(String msg){
 
		/* transformation de la chaine en tableau d'Octets */
		byte[] msgEnOctets = msg.getBytes();
 
		/* ajoute un octet codant le "1" au début du tableau passé en parametres */
		byte[] resultat = new byte[msgEnOctets.length+1];
		resultat[0] = 1;
		for (int i = 0; i < msgEnOctets.length; i++) {
			resultat[i+1] = msgEnOctets[i];
		}
 
		/* transforme le résultat en BigInteger */
		BigInteger msgEnBigInteger = new BigInteger(resultat);
 
		/* crypte le message par la méthode RSA grace a la clef publique (cela renvoi un BigInteger) */
		BigInteger msgCrypte = msgEnBigInteger.modPow(clePublic.getPublicExponent(), clePublic.getModulus());
 
		/* on retourne le message crypté sous la forme d'un tableau d'octets */
		return msgCrypte.toByteArray();
 
 
	}
 
	public String decrypter(byte[] msg){
 
		/* On repasse le tableau d'octets en BigInteger pour pouvoir le décrypter */
		BigInteger msgADecrypteEnBigInt = new BigInteger(msg);
 
		/* on décrypte le message grace au RSA et a la clef privée */
		BigInteger msgDecrypteEnBigInt = msgADecrypteEnBigInt.modPow(clePrivee.getPrivateExponent(), clePrivee.getModulus());
 
		/* on repasse le message en octets pour pouvoir retirer l'octet qu'on lui avait ajouté */
		byte[] msgDecrypteEnOctets = msgDecrypteEnBigInt.toByteArray();
 
		/* on lui retire son octet en plus */
		byte[] resultat = new byte[msgDecrypteEnOctets.length-1];
		for (int i = 0; i < resultat.length; i++) {
			resultat[i] = msgDecrypteEnOctets[i+1];
		}
 
		/* on retourne une chaine de charactères qui provient du tableau d'octets transformé */
		return new String (resultat);
 
	}
 
 
	/**
         * Permet de sauvegarder la cle publique dans le fichier
         * 'chemin'
         * @param chemin : chemin du fichier
         */
 
	public void sauvegarderClePub(String chemin){
 
		try {
			byte[]clePublicByte = clePublic.getEncoded();
			FileOutputStream fpub = new FileOutputStream(chemin+".pub");
			fpub.write(clePublicByte);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
 
		}catch (IOException e){
 
			e.printStackTrace();
 
		}
 
	}
 
	public RSAPublicKey recupererCle(String chemin){
 
		RSAPublicKey cle = null;
		KeyFactory keyFactory;
		try {
			keyFactory = KeyFactory.getInstance("RSA");
			FileInputStream pubFile = new FileInputStream(chemin+".pub");
			byte[] byte_pub = new byte[pubFile.available()];
			pubFile.read(byte_pub);
			X509EncodedKeySpec pubSpec = new X509EncodedKeySpec(byte_pub);
			cle = (RSAPublicKey) keyFactory.generatePublic(pubSpec);
			pubFile.close();
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvalidKeySpecException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
 
		return cle;
 
	}

la classe qui permet d'envoyer le fichier

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
 
 
public class MsgCle extends Message {
 
	private Socket soc;
	private File fichier;
 
	public MsgCle(Socket soc, File fichier){
		this.soc=soc;
		this.fichier=fichier;
	}
 
	@Override
	public void ecrire(DataOutputStream dos, String msg) {
		// TODO Auto-generated method stub
		int tailleFichier = (int)fichier.length();
		envoyerEntier(dos,17);
		envoyerEntier(dos,tailleFichier);
		envoyerFichier(fichier);
 
	}
 
	@Override
	public String lire(DataInputStream dis) {
		// TODO Auto-generated method stub
		return null;
	}
 
	public void envoyerFichier(File fichier){
 
 
		int nbOctets = 4096;
 
		if(fichier.exists()){
 
			OutputStream os = null;
 
			try {
				os = soc.getOutputStream();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
 
			//long tailleFichier = fichier.length();
			//long nbPassages = (tailleFichier/nbOctets) + 1;
 
			try {
				InputStream is = new BufferedInputStream(
									new FileInputStream(fichier));
 
				ByteArrayOutputStream tableaubytes = new ByteArrayOutputStream(); 
				BufferedOutputStream tampon = new BufferedOutputStream(tableaubytes); 
 
 
				int lu = is.read();
				int cpt = 0;
				int aecrire[] = new int[nbOctets];
 
				/* Tant qu on est pas a la fin du fichier*/
 
				while(lu != -1){
 
										                                      aecrire[cpt] = lu;
					cpt++;
					lu = is.read();
 
					if(cpt == 4096){
 
						cpt = 0;
						for(int i = 0; i<4096; i++){						
							tampon.write(aecrire[i]);
						}
						tampon.flush();
 
						os.write(tableaubytes.toByteArray());
						os.flush();
 
					}
 
					tableaubytes.reset();
 
				}
 
				/* on envoi le dernier paquet */
				System.out.println(aecrire.length);
				for(int i = 0; i<cpt; i++){	
					System.out.println("aecrire[i] "+(int)aecrire[i]);
					tampon.write(aecrire[i]);	
				}
 
				tampon.flush();
								 os.write(tableaubytes.toByteArray());
				os.flush();
 
				is.close();
				os.close();
				tampon.close();
 
 
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
 
		}else{
			System.out.println("Le  fichier "+fichier.getAbsolutePath()+" n existe pas");
		}
 
 
	}
 
}

et enfin la classe sur le client qui recoit le fichier

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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
 
 
public class MsgClePub extends Message{
 
	private Socket soc;
	private Controller control;
 
	public MsgClePub(Socket soc, Controller control){
		this.soc=soc;
		this.control=control;
	}
 
	@Override
	public void ecrire(DataOutputStream dos, String msg) {
		// TODO Auto-generated method stub
 
	}
 
	@Override
	public String lire(DataInputStream dis) {
		// TODO Auto-generated method stub
		int taille = lireEntier(dis);
		recevoirFichier(taille);
		return null;
	}
 
	private void recevoirFichier(int tailleFic){
 
 
		//int nb = tailleFic/6; /* TODO a voir par quoi diviser car le modulo doit etre 0*/
		boolean trouve = false;
		int nb = 0;
 
		for(int i = 4; trouve == false; i++){
 
			if(tailleFic % i == 0){
				nb = tailleFic/i;
				trouve = true;			
			}
 
		}
 
		byte[] buffer = new byte[tailleFic]; 
		int lu; 
		int cpt= 0;
		long taille = 0; 
		File fichier = null;
		OutputStream out = null;
		BufferedOutputStream outBuffer = null;
		try{
 
			fichier = new File("cle.pub");
			out = new FileOutputStream(fichier);
 
                                      while(cpt < tailleFic){
		   		/*getDis() retourne un            DataInputStream */
		   		control.getJoueur().getDis().readFully(buffer, cpt, nb);
		   		cpt += nb;
		   	}
 
                                       outBuffer.write(buffer);
			outBuffer.flush();
 
                           catch(EOFException e){
 
			System.out.println("fin de fichier");
 
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
 
		}finally{
 
			try {
				outBuffer.close();
				out.flush(); 
				out.close(); 
				//inBuffer.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
 
 
 
		}
 
	}
je vous mets egalement le thread qui est chargée de recevoir l'entier du serveur :

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
 
 
public class Reception extends Thread{
 
 
	private Joueur joueur;
	private Protocole protocole;
 
	public Reception(Joueur joueur, Protocole protocole){
		this.joueur = joueur;
		this.protocole = protocole;
	}
 
	public void run(){
 
		int code = 0;
		while(code != -1){
 
                                      /* La methode recevoirCode permet juste de                                       lire un entier (dis.readInt()). C'est ici, apres la reception du fichier, qu'il y a l exception EOFException*/
			code = joueur.recevoirCode();
 
                                      /* la classe protocole contient les methodes
                                       permettant de traiter les differents messages*/
			protocole.traiteCode(code);
 
		}
 
 
	}
 
}
Si quelqu'un voit d'ou peut venir cette exception je vous en serait reconnaissant

Merci d'avance