· 7 years ago · Apr 08, 2018, 08:10 PM
1import javax.crypto.Cipher;
2import javax.crypto.KeyGenerator;
3import javax.crypto.SecretKey;
4import javax.crypto.spec.IvParameterSpec;
5import javax.crypto.spec.SecretKeySpec;
6import java.io.*;
7import java.net.InetAddress;
8import java.net.Socket;
9import java.nio.charset.StandardCharsets;
10import java.nio.file.Files;
11import java.nio.file.Paths;
12import java.security.*;
13import java.util.Scanner;
14import java.util.logging.Level;
15import java.util.logging.Logger;
16import java.util.stream.Stream;
17
18public class Client {
19 private static boolean endComunication = false;
20 private static final byte[] IV_PARAM = {0x00, 0x01, 0x02, 0x03,
21 0x04, 0x05, 0x06, 0x07,
22 0x08, 0x09, 0x0A, 0x0B,
23 0x0C, 0x0D, 0x0E, 0x0F};
24 private static final String ADDRESS = "127.0.0.1";
25 private static final int PORT = 9090;
26
27 private static Message outMessage = null;
28 private static SecretKey secretKeyClient;
29 private static KeyPair keyPairClient;
30
31 private static PublicKey publicKeyServer;
32 private static byte[] mensajeEncriptado
33 ;
34 private static byte[] claveAESEncriptada;
35
36
37 public static void main(String[] args) {
38
39 System.out.println("CLIENT - START");
40 connect(ADDRESS, PORT);
41 System.out.println("CLIENT - END");
42
43 }
44
45 private static void connect(String address, int port) {
46
47 Socket socket;
48
49 try {
50 socket = new Socket(InetAddress.getByName(address), port);
51 while (!endComunication) {
52 processServerMessage(socket);
53 }
54 tancarSocket(socket);
55 } catch (IOException ex) {
56 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
57 }
58 }
59
60 private static void processServerMessage(Socket socket) {
61 ObjectInputStream objectInputStream;
62 ObjectOutputStream objectOutputStream;
63 Message inMessage;
64
65 try {
66 objectOutputStream = new ObjectOutputStream(socket.getOutputStream());
67
68 sendFirstMessage(objectOutputStream);
69
70 //TODO Me he quedado aquÃ
71
72 objectInputStream = new ObjectInputStream(socket.getInputStream());
73
74 do {
75
76 inMessage = (Message) objectInputStream.readObject();
77
78 switch (inMessage.getTypeMessage()) {
79 case "TANCARCONNEXIO":
80 System.out.println("CLIENT.procesarMissatgeDelServer(): tipusMissatge rebut= '" + inMessage.getTypeMessage() + "'.");
81 System.out.println("CLIENT.processComunicationWithServer(): recieved new message from server: '" + inMessage.toString());
82 endComunication = true;
83 break;
84 case "CHAT":
85 System.out.println("CLIENT.procesarMissatgeDelServer(): tipusMissatge rebut= '" + inMessage.getTypeMessage() + "'.");
86 System.out.println("CLIENT.processComunicationWithServer(): recieved new message from server: '" + inMessage.toString());
87 break;
88 case "RETORNCTRL":
89 System.out.println("CLIENT.procesarMissatgeDelServer(): tipusMissatge rebut= '" + inMessage.getTypeMessage() + "'.");
90 System.out.println("CLIENT.processComunicationWithServer(): recieved new message from server: '" + inMessage.toString());
91 break;
92 case "CLAUPUBLICA":
93 System.out.println("CLIENT.procesarMissatgeDelServer(): tipusMissatge rebut= '" + inMessage.getTypeMessage() + "'.");
94 System.out.println("CLIENT.processComunicationWithServer(): recieved new message from server: '" + inMessage.toString());
95 publicKeyServer = inMessage.getPublicKey();
96 break;
97 case "MISSATGEENCRIPTAT":
98 System.out.println("SERVER.procesarMissatgeDelClient(): tipusMissatge rebut= '" + inMessage.getTypeMessage() + "'.");
99 desencriptarMissatge(inMessage);
100 break;
101 case "FILE":
102 System.out.println("SERVER.procesarMissatgeDelClient(): tipusMissatge rebut= '" + inMessage.getTypeMessage() + "'.");
103 writeToFile(inMessage.getMessage(),"test.txt");
104 break;
105 }
106
107 if (!inMessage.getTypeMessage().equals("TANCARCONNEXIO")) {
108 respondToServer(objectOutputStream);
109
110 }
111
112
113 } while (!inMessage.getTypeMessage().equals("TANCARCONNEXIO") && !endComunication);
114
115 } catch (IOException ex) {
116 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
117 } catch (ClassNotFoundException e) {
118 e.printStackTrace();
119 }
120
121
122 }
123
124 private static void desencriptarMissatge(Message inMessage) {
125 Cipher cipher;
126 Key clauAESDesencriptada;
127 try {
128 cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
129 cipher.init(Cipher.DECRYPT_MODE, keyPairClient.getPrivate() );
130
131 clauAESDesencriptada =new SecretKeySpec( cipher.doFinal(inMessage.getKeyEncrypted()), "AES" );
132
133 cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
134 IvParameterSpec iv = new IvParameterSpec(IV_PARAM);
135 cipher.init(Cipher.DECRYPT_MODE, clauAESDesencriptada, iv);
136 byte[] stringDecryptedBytes = cipher.doFinal(inMessage.getMessageEncrypted());
137 String stringDecrypted = new String(stringDecryptedBytes);
138
139 System.out.println("SERVER.processComunicationWithClient(): recieved new encripted message from client: '" + stringDecrypted);
140
141
142 } catch (Exception e) {
143 e.printStackTrace();
144 }
145
146 }
147
148 private static void respondToServer(ObjectOutputStream objectOutputStream) {
149
150 boolean correctOption;
151 String option;
152
153 Scanner sc = new Scanner(System.in);
154 correctOption = false;
155 do {
156 System.out.println("---------------- SERVER ----------------");
157 System.out.println("0. Desconnectar-se del SERVER");
158 System.out.println();
159 System.out.println(" ENCRIPTACIÓ ASIMÈTRICA (RSA amb clau embolcallada)");
160 System.out.println("1. Generar clau simètrica i público-privades");
161 System.out.println("2. Enviar clau pública al SERVER");
162 System.out.println("3. Encriptar missatge amb RSA amb clau embolcallada");
163 System.out.println("4. Enviar el missatge encriptat al SERVER");
164 System.out.println();
165 System.out.println(" SENSE ENCRIPTACIÓ");
166 System.out.println("11. Enviar un missatge al SERVER (chat)");
167 System.out.println("12. Retornar el control de les comunicacions al SERVER");
168 System.out.println();
169 System.out.println("21. Enviar un fitxer al SERVER");
170 System.out.println();
171 System.out.println("50. Tancar el programa (equival al menú 0)");
172 System.out.println();
173 System.out.print("opció?: ");
174
175
176 option = sc.next();
177
178 switch (option) {
179 case "0":
180 outMessage = new Message("TANCARCONNEXIO", "El client tanca la comunicació.");
181 correctOption = true;
182 endComunication = true;
183 break;
184 case "1":
185 secretKeyClient = generadorDeClausSimetriques(128);
186 keyPairClient = menu1(512);
187 System.out.print("CLIENT.procesarMissatgeDelClient(): claus creadas al Client: ");
188
189 break;
190 case "2":
191 if (secretKeyClient == null || keyPairClient == null) {
192 System.out.print("CLIENT.procesarMissatgeDelServer(): les claus encara no estan creades, utiliza el menu 1. " + "\n");
193 } else {
194 outMessage = new Message("CLAUPUBLICA", keyPairClient.getPublic(), "Clau publica enviada al server.");
195 correctOption = true;
196 }
197
198 break;
199 case "3":
200
201 if (secretKeyClient == null || keyPairClient == null) {
202 System.out.print("CLIENT.procesarMissatgeDelServer(): les claus encara no estan creades, utiliza el menu 1. " + "\n");
203
204 } else if (publicKeyServer == null) {
205 System.out.print("CLIENT.procesarMissatgeDelClient(): El server encara no ha enviat la seva clau publica. " + "\n");
206
207 } else {
208 Scanner sc3 = new Scanner(System.in);
209 System.out.print("SERVER.procesarMissatgeDelClient(): quin missatge vols enviar al client encriptat?: ");
210
211 String missatgeAEncriptar = sc3.nextLine();
212
213 mensajeEncriptado = encriptarMensaje(missatgeAEncriptar);
214
215 claveAESEncriptada = encriptarClave(publicKeyServer);
216
217
218 }
219
220 break;
221 case "4":
222
223 outMessage = new Message("MISSATGEENCRIPTAT", mensajeEncriptado, claveAESEncriptada);
224 correctOption = true;
225
226 break;
227 case "11":
228 Scanner sc2 = new Scanner(System.in);
229 System.out.print("CLIENT.procesarMissatgeDelServer(): quin missatge vols enviar al server?: ");
230
231 String missatge = sc2.nextLine();
232 outMessage = new Message("CHAT", missatge);
233 correctOption = true;
234 break;
235 case "12":
236 outMessage = new Message("RETORNCTRL", "El client retorna el control de les comunicacions al server.");
237 correctOption = true;
238 break;
239 case "21":
240
241 String readMessage = readFile("test.txt");
242 outMessage = new Message("FILE", readMessage);
243 correctOption = true;
244 break;
245 case "50":
246 outMessage = new Message("TANCARCONNEXIO", "El client tanca la comunicació.");
247 correctOption = true;
248 endComunication = true;
249 break;
250 default:
251 System.out.println("COMANDA NO RECONEGUDA");
252 }
253 } while (!correctOption);
254
255 sendResponseToServer(outMessage, objectOutputStream);
256
257
258 }
259
260 private static void sendResponseToServer(Message reply, ObjectOutputStream objectOutputStream) {
261 try {
262
263 objectOutputStream.writeObject(reply);
264 objectOutputStream.flush();
265
266 } catch (IOException e) {
267 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, e);
268 }
269 }
270
271 private static void sendFirstMessage(ObjectOutputStream objectOutputStream) {
272 try {
273 objectOutputStream.writeObject(new Message("INICIO", "Iniciando conexion"));
274 objectOutputStream.flush();
275 } catch (IOException e) {
276 e.printStackTrace();
277 }
278
279 }
280
281
282 private static void tancarSocket(Socket clientSocket) {
283
284 if ((clientSocket != null) && (!clientSocket.isClosed())) {
285 try {
286 if (!clientSocket.isInputShutdown()) {
287 clientSocket.shutdownInput();
288 }
289 if (!clientSocket.isOutputShutdown()) {
290 clientSocket.shutdownOutput();
291 }
292 clientSocket.close();
293 } catch (IOException ex) {
294 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
295 }
296 }
297 }
298
299 private static KeyPair menu1(int len) {
300 KeyPair clauPublicaIPrivada = null;
301
302 try {
303 KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
304 keyGen.initialize(len);
305 clauPublicaIPrivada = keyGen.genKeyPair();
306 } catch (Exception ex) {
307 System.err.println("ERROR: R.E.generadorDeClausAsimetriques() - Generador de claus asimètriques (pública i privada) no disponible." + ex);
308 }
309 return clauPublicaIPrivada;
310 }
311
312 private static SecretKey generadorDeClausSimetriques(int clauTamany) {
313 SecretKey sKey = null;
314 if ((clauTamany == 128) || (clauTamany == 192) || (clauTamany == 256)) {
315 try {
316 KeyGenerator kgen = KeyGenerator.getInstance("AES");
317 kgen.init(clauTamany);
318 sKey = kgen.generateKey();
319 } catch (NoSuchAlgorithmException ex) {
320 System.err.println("Generador no disponible.");
321 }
322 }
323 return sKey;
324 }
325
326 private static byte[] encriptarClave(PublicKey aPublic) {
327
328 byte[] clauAESEncriptadaEnByte = new byte[0];
329 try {
330 Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
331 cipher.init(Cipher.WRAP_MODE, aPublic);
332 clauAESEncriptadaEnByte = cipher.wrap(secretKeyClient);
333
334
335 } catch (Exception e) {
336 e.printStackTrace();
337 }
338 return clauAESEncriptadaEnByte;
339 }
340
341 private static byte[] encriptarMensaje(String missatgeAEncriptar) {
342 byte[] dadesAEncriptarEnByte = missatgeAEncriptar.getBytes();
343 Cipher cipher;
344 byte[] dadesEncriptadesEnByte = new byte[0];
345
346 try {
347 cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
348 IvParameterSpec iv = new IvParameterSpec(IV_PARAM);
349 cipher.init(Cipher.ENCRYPT_MODE, secretKeyClient, iv);
350
351 dadesEncriptadesEnByte = cipher.doFinal(dadesAEncriptarEnByte);
352
353 } catch (Exception e) {
354 e.printStackTrace();
355 }
356
357
358 return dadesEncriptadesEnByte;
359 }
360
361 private static String readFile(String filePath){
362 StringBuilder contentBuilder = new StringBuilder();
363 try (Stream<String> stream = Files.lines(Paths.get(filePath), StandardCharsets.UTF_8)){
364 stream.forEach(s -> contentBuilder.append(s).append("\n"));
365
366 }catch (IOException e){
367 e.printStackTrace();
368 }
369
370 return contentBuilder.toString();
371 }
372
373 private static void writeToFile(String message, String filename) throws IOException {
374
375 File file = new File(filename);
376 file.createNewFile();
377
378 BufferedWriter writer = new BufferedWriter(new FileWriter(filename));
379 writer.write(message);
380 writer.close();
381 }
382}