· 8 years ago · Jan 04, 2018, 05:22 PM
1package client;
2
3import com.google.gson.JsonElement;
4import com.google.gson.JsonIOException;
5import com.google.gson.JsonObject;
6import com.google.gson.JsonParser;
7import com.google.gson.JsonSyntaxException;
8import com.google.gson.stream.JsonReader;
9import java.io.BufferedOutputStream;
10import java.io.File;
11import java.io.FileInputStream;
12import java.io.FileNotFoundException;
13import java.io.FileOutputStream;
14import java.io.InputStreamReader;
15import java.net.Socket;
16
17import java.io.IOException;
18import java.io.InputStream;
19import java.io.OutputStream;
20import java.io.UnsupportedEncodingException;
21import java.nio.charset.StandardCharsets;
22import java.security.InvalidKeyException;
23import java.security.KeyFactory;
24import java.security.KeyPair;
25import java.security.KeyPairGenerator;
26import java.security.KeyStore;
27import java.security.KeyStoreException;
28import java.security.MessageDigest;
29import java.security.NoSuchAlgorithmException;
30import java.security.NoSuchProviderException;
31import java.security.PrivateKey;
32import java.security.Provider;
33import java.security.PublicKey;
34import java.security.Security;
35import java.security.Signature;
36import java.security.SignatureException;
37import java.security.UnrecoverableKeyException;
38import java.security.cert.Certificate;
39import java.security.cert.CertificateException;
40import java.security.cert.CertificateExpiredException;
41import java.security.cert.X509Certificate;
42import java.security.spec.InvalidKeySpecException;
43import java.security.spec.PKCS8EncodedKeySpec;
44import java.security.spec.X509EncodedKeySpec;
45import java.util.Base64;
46import java.util.Enumeration;
47import java.util.Scanner;
48import java.util.logging.Level;
49import java.util.logging.Logger;
50import javax.crypto.BadPaddingException;
51import javax.crypto.Cipher;
52import javax.crypto.IllegalBlockSizeException;
53import javax.crypto.KeyGenerator;
54import javax.crypto.Mac;
55import javax.crypto.NoSuchPaddingException;
56import javax.crypto.SecretKey;
57
58/**
59 *
60 * @author Mário Madeira, Pedro Geraldo
61 */
62public final class Client {
63
64 JsonReader input;
65 OutputStream output;
66 Socket socket;
67
68 int usrID;
69 String usrUUID;
70 int sessionID;
71 SecretKey sessionKey;
72
73 Client() {
74 try {
75 //Ligação ao Servidor
76 socket = new Socket("localhost", 31444);
77 input = new JsonReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
78 output = socket.getOutputStream();
79 } catch (IOException ex) {
80 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
81 }
82
83 sessionKey = sessionKey();
84 String jsonHead = "\"type\":\"session\"";
85 String jsonBody = ",\"sessionKey\":\"" + new String(Base64.getEncoder().encode(sessionKey.getEncoded())) + "\"";
86 String jsonMac = ",\"mac\":\"" + new String(Base64.getEncoder().encode(genMAC(jsonHead + jsonBody))) + "\"";
87
88 JsonObject result = sendResult(jsonHead + jsonBody + jsonMac, null);
89
90 /*
91 * Scanner sc = new Scanner(System.in);
92 * System.out.println("Introduza o uuid do utilizador");
93 * usrUUID = sc.nextLine();
94 *
95 */
96 try {
97 sessionID = result.get("result").getAsInt();
98 } catch (Error err) {
99 }
100
101 /* try
102 * {
103 * keyPairGenerate(usrID);
104 * }
105 * catch (IOException | NoSuchAlgorithmException |
106 * NoSuchProviderException ex)
107 * {
108 * Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
109 * }
110 */
111 }
112
113 /**
114 * Main
115 *
116 * @param args
117 * @throws java.lang.Exception
118 */
119 public static void main(String[] args) throws Exception {
120 Client client = new Client();
121 client.menu();
122 }
123
124 public void menu() {
125 String json;
126 int op;
127
128 do {
129 System.out.println("1 - Criar");
130 System.out.println("2 - Entrar");
131 System.out.println("0 - Sair");
132 Scanner sc = new Scanner(System.in);
133 op = sc.nextInt();
134
135 switch (op) {
136 case 1: {
137 try {
138 Scanner cs = new Scanner(System.in);
139 String pp = cs.nextLine();
140 String cc = new String(Base64.getEncoder().encode(getCC()));
141 String result = "\"type\":\"create\",\"uuid\":\""+ pp + "\",\"cartao\":\""+ cc +"\"";
142 String jsonMac = ",\"mac\":\"" + new String(Base64.getEncoder().encode(genMAC(result))) + "\"";
143 JsonObject js = sendResult(result + jsonMac, null);
144 usrID = js.get("result").getAsInt();
145 menuAuth();
146 } catch (NoSuchAlgorithmException ex) {
147 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
148 } catch (KeyStoreException ex) {
149 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
150 } catch (IOException ex) {
151 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
152 } catch (CertificateException ex) {
153 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
154 }
155 }
156 break;
157 case 2: {
158 try {
159 Scanner cs = new Scanner(System.in);
160 String pp = cs.nextLine();
161 String cc = new String(Base64.getEncoder().encode(getCC()));
162 String result = "\"type\":\"create\",\"uuid\":\""+ pp + "\",\"cartao\":\""+ cc +"\"";
163 String jsonMac = ",\"mac\":\"" + new String(Base64.getEncoder().encode(genMAC(result))) + "\"";
164 JsonObject js = sendResult(result + jsonMac, null);
165 usrID = js.get("result").getAsInt();
166 menuAuth();
167 } catch (NoSuchAlgorithmException ex) {
168 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
169 } catch (KeyStoreException ex) {
170 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
171 } catch (IOException ex) {
172 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
173 } catch (CertificateException ex) {
174 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
175 }
176 }
177 break;
178 case 0: //Sair
179 break;
180 default:
181 System.out.println("Por favor introduza uma opcao existente");
182 break;
183 }
184 } while (op != 0);
185 try {
186 socket.close();
187 } catch (IOException ex) {
188 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
189 }
190 }
191
192 public void menuAuth() {
193 //DECLARAÇÃO DE VARIAVEIS
194 String msg;
195 String msgDestino;
196 String copiaMsg = "";
197 String AssinaturaMsg;
198 String idMsg;
199 int op;
200
201 do {
202 System.out.println("4 - Enviar mensagem");
203 System.out.println("2 - Caixa de Entrada");
204 System.out.println("3 - Listar todas as mensagens");
205 System.out.println("1 - Listar utilizadores");
206 System.out.println("5 - Recv");
207 System.out.println("6 - Receipt");
208 System.out.println("7 - Status");
209 System.out.println("0 - Sair");
210 Scanner sc = new Scanner(System.in);
211 op = sc.nextInt();
212
213 switch (op) {
214 case 1: //LIST
215 msg = ("\"type\":\"list\"");
216 sendResult(msg, null);
217 break;
218
219 case 2: //NEW
220 msg = ("\"type\":\"new\",\"id\":\"" + usrID + "\"");
221 sendResult(msg, null);
222 break;
223
224 case 3: //ALL
225 msg = ("\"type\":\"all\",\"id\":\"" + usrID + "\"");
226 sendResult(msg, null);
227 break;
228
229 case 4: //SEND
230// System.out.println("Introduza o id do Destinatario da mensagem");
231// idDestinatario = sc.nextInt();
232// System.out.println("Escreva a sua mensagem");
233// Scanner scSend = new Scanner(System.in);
234// msgDestino = scSend.nextLine();
235// copiaMsg = msgDestino;
236// msg = ("\"type\":\"send\",\"src\":\"" + usrID + "\",\"dst\":\"" + idDestinatario + "\",\"msg\":\"" + mensagem(msgDestino) + "\",\"copy\":\"" + copiaMsg + "\"");
237// sendResult(msg, null);
238 break;
239
240 case 5: //RECV
241 System.out.println("Introduza o id");
242 usrID = sc.nextInt();
243 System.out.println("Introduza o id da Mensagem");
244 Scanner scRecv = new Scanner(System.in);
245 idMsg = scRecv.nextLine();
246 msg = ("\"type\":\"recv\",\"id\":\"" + usrID + "\",\"msg\":\"" + idMsg + "\"");
247 sendResult(msg, null);
248 break;
249
250 case 6: //RECEIPT
251 System.out.println("Introduza o id");
252 usrID = sc.nextInt();
253 System.out.println("Introduza o id da mensagem");
254 Scanner scIdMsg = new Scanner(System.in);
255 idMsg = scIdMsg.nextLine();
256 System.out.println("Introduza a assinatura da msg");
257 AssinaturaMsg = sc.nextLine();
258 msg = ("\"type\":\"receipt\",\"id\":\"" + usrID + "\",\"msg\":\"" + idMsg + "\",\"receipt\":\"" + AssinaturaMsg + "");
259 sendResult(msg, null);
260 break;
261
262 case 7: //STATUS
263 System.out.println("Introduza o id");
264 usrID = sc.nextInt();
265 System.out.println("Introduza o id da mensagem enviada");
266 idMsg = sc.nextLine();
267 msg = ("\"type\":\"status\",\"id\":\"" + usrID + "\",\"msg\"" + idMsg + "");
268 sendResult(msg, null);
269 break;
270
271 default:
272 System.out.println("Por favor introduza uma opcao existente");
273 break;
274 }
275 } while (op != 0);
276 try {
277 socket.close();
278 } catch (IOException ex) {
279 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
280 }
281 }
282
283 boolean calcMAC(String json, int sessionID) {
284 return false;
285 }
286
287
288 //MAC Algorithm Generator
289 public byte[] genMAC(String json) {
290 Mac mac;
291 try {
292 mac = Mac.getInstance(sessionKey.getAlgorithm());
293 mac.init(sessionKey);
294
295 byte[] b = json.getBytes("UTF-8");
296 return mac.doFinal(b);
297 } catch (NoSuchAlgorithmException | InvalidKeyException | UnsupportedEncodingException ex) {
298 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
299 return null;
300 }
301 }
302
303 //MENSAGEM QUE ENVIA AO SERVIDOR
304 JsonObject sendResult(String result, String error) {
305 String msg = "{";
306 // Usefull result
307 if (result != null) {
308 msg += result;
309 }
310 // error message
311 if (error != null) {
312 msg += "\"error\":" + error;
313 }
314 msg += "}\n";
315 try {
316 System.out.print("Envio ao servidor: " + msg);
317 output.write(msg.getBytes(StandardCharsets.UTF_8));
318 return readResult();
319
320 } catch (IOException ex) {
321 Logger.getLogger(Client.class
322 .getName()).log(Level.SEVERE, null, ex);
323 }
324 return null;
325 }
326
327 //MENSAGEM QUE RECEBE DO SERVIDOR
328 JsonObject readResult() {
329 try {
330 JsonElement data = new JsonParser().parse(input);
331 if (data.isJsonObject()) {
332 System.out.println("Resultado do servidor: " + data.getAsJsonObject());
333 return data.getAsJsonObject();
334 }
335 System.err.print("Nenhum resultado do servidor\n");
336 return null;
337 } catch (JsonIOException | JsonSyntaxException e) {
338 System.err.print("Error while reading JSON command from socket, connection will be shutdown\n");
339 return null;
340 }
341
342 }
343
344 //GERACAO DE CHAVE DE SESSAO
345 SecretKey sessionKey() {
346 KeyGenerator keyGen;
347 try {
348 keyGen = KeyGenerator.getInstance("HmacMD5");
349 //SecretKey sk = keyGen.generateKey();
350 //byte[] keyBytes = sk.getEncoded();
351 //String key = new String(keyBytes);
352
353 //return new String(keyBytes);
354 //return sk.getEncoded();
355 return keyGen.generateKey();
356 } catch (NoSuchAlgorithmException ex) {
357 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
358 return null;
359 }
360 }
361
362 //GERACAO DE CHAVE ASSIMETRICAS
363 void keyPairGenerate(int id) throws IOException, NoSuchAlgorithmException, NoSuchProviderException {
364 KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
365 kpg.initialize(1024);
366
367 KeyPair pair = kpg.generateKeyPair();
368 PublicKey pub = pair.getPublic(); //Chave Pública
369 PrivateKey priv = pair.getPrivate(); //Chave Privada
370 byte[] pubKey = pub.getEncoded();
371 byte[] privKey = priv.getEncoded();
372
373 File verifica = new File("keyBox\\" + id);
374
375 if (verifica.exists() != true) {
376 verifica.mkdir();
377 FileOutputStream fos = new FileOutputStream("keyBox\\" + id + "\\publico.txt");
378 FileOutputStream fus = new FileOutputStream("keyBox\\" + id + "\\privado.txt");
379 fos.write(pubKey);
380 fus.write(privKey);
381 fos.close();
382 fus.close();
383 }
384 }
385
386 //Certificado
387 public String certificado(String msg, String cript) throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, UnrecoverableKeyException, InvalidKeyException, FileNotFoundException, SignatureException {
388
389 //String to Bytes
390 byte[] msg_bytes = msg.getBytes();
391
392 //Listar Providers
393 Provider[] provs = Security.getProviders();
394 Provider provCartao = null;
395
396 for (int i = 0; i < provs.length; i++) {
397 String prov_name = provs[i].getName();
398 System.out.println(i + " -Nome do Provider: " + prov_name);
399 if (prov_name.contains("CartaoCidadao")) {
400 provCartao = provs[i];
401 }
402
403 }
404
405 //KeyStore
406 KeyStore ks = KeyStore.getInstance("PKCS11", provCartao);
407 ks.load(null, null);
408
409 //Listar Conteúdo dos Certificados
410 /*
411 * Enumeration<String> als = ks.aliases();
412 * while (als.hasMoreElements())
413 * {
414 * System.out.println(als.nextElement());
415 * }
416 */
417 //Certificado
418 String alias = "CITIZEN SIGNATURE CERTIFICATE";
419 java.security.cert.Certificate c = ks.getCertificate(alias);
420 PrivateKey privkey = (PrivateKey) ks.getKey(alias, null);
421
422 PublicKey pubkey = c.getPublicKey(); //Retorn PublicKey do Certificado
423 byte[] certificado = c.getEncoded();
424
425 //Assinatura
426 byte[] signed = assinatura(msg_bytes, privkey, pubkey);
427
428 return "[{\"assinatura\":" + signed
429 + "\"publicKey\":" + pubkey
430 + "\"certificado\":" + certificado
431 + "\"mensagem\":" + cript
432 + "}]";
433 }
434
435 //Criptografia
436 public String cript(String msg, int id) {
437 byte[] msg_byte = msg.getBytes();
438
439 InputStream is;
440 try {
441 is = new FileInputStream("keyBox\\" + id + "\\publico.txt");
442 byte[] pub = new byte[is.available()];
443 is.read(pub);
444 System.out.println(id);
445
446 X509EncodedKeySpec keyP = new X509EncodedKeySpec(pub);
447 KeyFactory kf = KeyFactory.getInstance("RSA");
448 PublicKey pKey = kf.generatePublic(keyP);
449
450 Cipher cp = Cipher.getInstance("RSA");
451 cp.init(Cipher.ENCRYPT_MODE, pKey);
452 cp.doFinal(msg_byte);
453
454 return new String(msg_byte);
455 } catch (IOException | NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException ex) {
456 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
457 return null;
458 }
459
460 }
461
462 //Decriptografia
463 public String decript(byte[] msg, int id) throws FileNotFoundException, IOException, NoSuchAlgorithmException, InvalidKeySpecException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
464 FileInputStream privt = new FileInputStream("keyBox\\" + id + "\\privado.txt");
465 byte[] priv = new byte[privt.available()];
466 privt.read(priv);
467
468 PKCS8EncodedKeySpec keyPv = new PKCS8EncodedKeySpec(priv);
469 KeyFactory kf = KeyFactory.getInstance("RSA");
470 PrivateKey key = kf.generatePrivate(keyPv);
471
472 Cipher cp = Cipher.getInstance("RSA");
473 cp.init(Cipher.DECRYPT_MODE, key);
474 byte[] decifrado = cp.doFinal(msg);
475 String deci = new String(decifrado);
476
477 return deci;
478 }
479
480 //CC Criação
481 public byte[] getCC() throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException {
482 MessageDigest md = MessageDigest.getInstance("SHA-256");
483 Provider prov = Security.getProvider("SunPKCS11-CartaoCidadao");
484 KeyStore ks = KeyStore.getInstance("PKCS11", prov);
485 ks.load(null, null);
486 Certificate cert = ks.getCertificate("CITIZEN AUTHENTICATION CERTIFICATE");
487
488 md.update(cert.getEncoded());
489 byte[] cc = md.digest();
490
491 return cc;
492 }
493
494 //ASSINATURA DIGITAL
495 public byte[] assinatura(byte[] msg, PrivateKey priv, PublicKey pub) throws NoSuchAlgorithmException, InvalidKeyException, FileNotFoundException, IOException, SignatureException {
496 Signature sg = Signature.getInstance("SHA256withRSA"); //Assinatura
497 sg.initSign(priv);
498
499 //int length;
500 //byte[] buffer = msg;
501 //InputStream in = null;
502 sg.update(msg);
503
504 byte[] signed = sg.sign();
505
506 return signed;
507 }
508
509 //MENSAGEM A SER ENVIADA PARA OUTRO USER
510 byte[] mensagem(String msgDestino) {
511 byte[] encodedBytes = null;
512// try
513// {
514// String cript = cript(msgDestino, idDestinatario);
515// encodedBytes = Base64.getEncoder().encode(certificado(msgDestino, cript).getBytes());
516// }
517// catch (IOException | NoSuchAlgorithmException | InvalidKeyException | KeyStoreException | CertificateException | UnrecoverableKeyException | SignatureException ex)
518// {
519// Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, ex);
520// }
521 return encodedBytes;
522 }
523
524 //VERIFICA VALIDADE
525 public void validade() throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException {
526
527 Provider[] provs = Security.getProviders();
528 Provider prov = null;
529 for (int i = 0; i < provs.length; i++) {
530 String prov_name = provs[i].getName();
531 System.out.println(i + " - Nome do provider: " + prov_name);
532 if (prov_name.contains("CartaoCidadao")) {
533 prov = provs[i];
534 }
535 }
536
537 KeyStore ks = KeyStore.getInstance("PKCS11", prov);
538 ks.load(null, null);
539
540 Certificate cert = ks.getCertificate("CITIZEN AUTHENTICATION CERTIFICATE");
541
542 X509Certificate x509cert = (X509Certificate) cert;
543 try {
544 x509cert.checkValidity();
545 } catch (CertificateExpiredException ex) {
546 System.out.println("Certificado expirado");
547 }
548 System.out.println("Certificado válido");
549 }
550
551}