Envoi d un fichier par tableau de byte
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:
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:
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:
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:
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