Salta el contingut
 

Pràctica 4: Seguretat i criptografia

Joan Puigcerver Ibáñez

Llicència: CC BY-NC-SA 4.0

(Reconeixement - NoComercial - CompartirIgual) 🅭

Entrega

L'entrega ha de complir els requisits següents:

  • Paquet: el codi ha d'estar en el paquet corresponent: ud4.practices
  • Nom de la classe: la classe on comença l'execució (main()) de cada exercici té com a nom el títol de l'exercici.
  • Format de l'eixida: ha de ser consistent amb el format demanat.
  • Lliurament: un fitxer .zip amb el contingut del paquet.
  • Repositori: el codi ha d'estar pujat a GitHub, al teu repositori del mòdul.
  • Etiqueta de GitHub: PracticeCrypt ( Create a tag in a GitHub repository – StackOverflow).

FileEncryption

ud4.practices.fileencryption

Crea l'aplicació FileEncryption que permeta crear, llegir i escriure en fitxers encriptats mitjançant l'algorisme AES. L'aplicació ha de mostrar el menú següent i permetre a la persona usuària realitzar les accions indicades:

Benvingut a FileEncryption:
1) Escriure un fitxer
2) Llegir un fitxer
0) Eixir.

L'acció Eixir acaba el programa.

El codi ha d'estar ben estructurat en mètodes i classes.

Escriure un fitxer

La persona usuària indica la ruta del fitxer on vol guardar la informació i el programa comprova si el fitxer existeix. Si existeix, el programa demana confirmació per sobreescriure'l i, si no es confirma, torna al menú principal.

A continuació, el programa demana una contrasenya i crea una SecretKey a partir d'ella. Després, demana que s'escriga per pantalla tota la informació que es vol guardar en el fitxer, i deixa de demanar-la quan s'escriu una línia amb el contingut \exit. Finalment, encripta tot el contingut i el guarda en el fitxer especificat.

Llegir un fitxer

La persona usuària indica la ruta del fitxer que vol llegir i el programa comprova si el fitxer existeix. Si no existeix, mostra un missatge d'error i torna al menú principal.

A continuació, el programa demana una contrasenya, crea una SecretKey a partir d'ella i intenta desencriptar el fitxer. Si la desencriptació ha sigut satisfactòria, mostra per pantalla el contingut del fitxer desencriptat. En cas contrari (per exemple, perquè la contrasenya no és l'adequada o el fitxer no estava encriptat), mostra un missatge d'error.

SSLSocket: Chat

ud4.practices.chat

Adapta el codi de l'aplicació de l' Exercici: Chat perquè utilitze SSLSocket.

Codi de l'exercici Chat solucionat
  • Client:

    ChatClient.java
    package ud3.exercises.chat.client;
    
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class ChatClient {
        private final Socket socket;
        private final ChatClientListener listener;
        private final Scanner scanner;
        private final PrintWriter out;
    
        public ChatClient(String host, int port) throws IOException {
            this.scanner = new Scanner(System.in);
            this.socket = new Socket(host, port);
            this.out = new PrintWriter(socket.getOutputStream(), true);
            this.listener = new ChatClientListener(socket.getInputStream());
        }
    
        public void identify(){
            System.out.print("Introdueix el teu nom: ");
            String line = scanner.nextLine();
            out.println(line);
            listener.start();
        }
    
        public void chat() throws IOException {
            System.out.println("Acabes d'entrar al chat.");
            System.out.println("Per exir, escriu \"/exit\".");
            String line;
            while(!(line = scanner.nextLine()).equals("/exit") && this.socket.isConnected()){
                out.println(line);
            }
            close();
        }
    
        public void close(){
            try {
                socket.close();
                listener.interrupt();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    
        public static void main(String[] args) {
            System.out.println("Connectant-se amb el servidor...");
            try {
                ChatClient chat = new ChatClient("localhost", 1234);
                chat.identify();
                chat.chat();
            } catch (IOException e){
                System.err.println("Error connectant-se amb el servidor.");
            }
        }
    }
    
    ChatClientListener.java
    package ud3.exercises.chat.client;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.net.Socket;
    
    public class ChatClientListener extends Thread {
    
        private final BufferedReader in;
    
        public ChatClientListener(InputStream inputStream) throws IOException {
            in = new BufferedReader(new InputStreamReader(inputStream));
        }
    
        @Override
        public void run() {
            String line;
            try {
                while ((line = in.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (IOException ignored ){
            }
        }
    }
    
  • Servidor:

    ChatServer.java
    package ud3.exercises.chat.server;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Scanner;
    
    public class ChatServer extends Thread {
        ServerSocket server;
    
        List<ChatServerHandler> clients;
        boolean running;
    
        public ChatServer(int port) throws IOException {
            server = new ServerSocket(port);
            clients = new ArrayList<>();
            running = true;
        }
    
        public void close(){
            running = false;
            this.interrupt();
        }
    
        public synchronized void removeClient(ChatServerHandler client){
            clients.remove(client);
        }
    
        public void sendMessage(String msg){
            for(ChatServerHandler client : clients) {
                client.sendMessage(msg);
            }
        }
    
        public void sendMessage(String alias, String msg){
            clients.stream()
                    .filter(client -> !client.getNom().equals(alias))
                    .forEach(client -> client.sendMessage(msg));
        }
    
        @Override
        public void run() {
            while (running){
                try {
                    Socket client = server.accept();
                    ChatServerHandler handler = new ChatServerHandler(client, this);
                    clients.add(handler);
                    handler.start();
                    System.out.println("Nova connexió acceptada.");
                } catch (IOException e) {
                    System.err.println("Error while accepting new connection");
                    System.err.println(e.getMessage());
                }
            }
        }
    
        public static void main(String[] args) {
            try {
                Scanner scanner = new Scanner(System.in);
                ChatServer server = new ChatServer(1234);
                server.start();
    
                scanner.nextLine();
    
                server.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
    
        }
    }
    
    ChatServerHandler.java
    package ud3.exercises.chat.server;
    
    import java.io.*;
    import java.net.Socket;
    
    public class ChatServerHandler extends Thread {
        private final Socket socket;
        private final ChatServer server;
        private final PrintWriter out;
        private final BufferedReader in;
    
        private String nom;
        public ChatServerHandler(Socket socket, ChatServer server) throws IOException {
            this.socket = socket;
            this.server = server;
    
            this.in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            this.out = new PrintWriter(socket.getOutputStream(), true);
        }
    
        public String getNom() {
            return nom;
        }
    
        public void setNom(String nom) {
            this.nom = nom;
        }
    
        public void sendMessage(String message){
            out.println(message);
        }
    
        @Override
        public void run(){
            try {
                String nom = in.readLine();
                setNom(nom);
    
                System.out.printf("%s s'ha identificat.\n", getNom());
    
                // Quan un client es desconecta, l'operació readLine() retorna null
                String message;
                while((message = in.readLine()) != null){
                    String messageWithName = String.format("%s: %s", getNom(), message);
                    System.out.println(messageWithName);
                    server.sendMessage(messageWithName);
                }
                System.out.printf("%s has disconnected.\n", getNom());
                socket.close();
            } catch (IOException e) {
                System.err.println(e.getMessage());
            } finally {
                server.removeClient(this);
            }
        }
    }
    

Cal generar els elements següents:

  • KeyStore de ChatServer: guarda-la en el fitxer files/ud4/chat/chat-server.jks. Indica l'ordre utilitzada com a comentari en el moment que es cree el SSLServerSocket en la classe ChatServer. El certificat ha de tindre les dades següents:

    Camp Valor
    Àlies chat-server
    CN ChatServer
    OU PSP-DAM2S
    O CIPFP Mislata
    L Mislata
    ST València
    C ES

    La informació del certificat s'ha de mostrar per terminal quan s'inicie el servidor.

  • TrustStore de ChatClient: guarda-la en el fitxer files/ud4/chat/chat-client.jks. Indica l'ordre utilitzada com a comentari en el moment que es cree el SSLSocket en la classe ChatClient. Cal importar-hi el certificat del servidor generat anteriorment.

📌 Aquest document pot quedar desactualitzat després d’imprimir-lo. Pots consultar la versió més recent a la pàgina web.
🌿 Abans d’imprimir aquest document, considera si és realment necessari. Redueix el consum de paper i ajuda a protegir el nostre entorn.