diff --git a/src/Main/Main.java b/src/Main/Main.java index 0c5e865..aeb9cce 100644 --- a/src/Main/Main.java +++ b/src/Main/Main.java @@ -139,14 +139,26 @@ public static void main(String[] args) throws IOException { switch (command.toLowerCase()) { case "upload": // Start a new thread for upload - FileData fileupload = new FileData(argument); - System.out.println("The Hash of the File is " + fileupload.getFileHash()); - Handshake.registerFile(fileupload , argument); - break; + String filePath = argument; + FileData fileupload = new FileData(filePath); + + System.out.print("Set password for this file? (leave empty for no password): "); + String password = scanner.nextLine().trim(); + + if (!password.isEmpty()) { + fileupload.setPasswordHash(FileData.hashPassword(password)); + System.out.println("Password protection enabled"); + } + + System.out.println("The Hash of the File is " + fileupload.getFileHash()); + Handshake.registerFile(fileupload , filePath); + break; case "download": - // Start a new thread for download - FileReciever.downloadFile(argument, central); - + // Start a new thread for download + System.out.print("File password (leave empty if none): "); + String downloadPassword = scanner.nextLine().trim(); + FileReciever.downloadFile(argument, central, downloadPassword); + break; case "broadcastfile": FileData f = new FileData(argument); diff --git a/src/discovery/FileData.java b/src/discovery/FileData.java index 2e81549..fb921f3 100644 --- a/src/discovery/FileData.java +++ b/src/discovery/FileData.java @@ -15,6 +15,7 @@ public class FileData implements Serializable{ private long fileSize; // Size in bytes private String fileType; // MIME type or file extension private String fileHash; // Checksum or hash for integrity verification + private String passwordHash; //SHA-256 hash of Password // Constructors public FileData() { @@ -77,6 +78,14 @@ public void setFileHash(String fileHash) { this.fileHash = fileHash; } + public String getPasswordHash() { + return passwordHash; + } + + public void setPasswordHash(String passwordHash) { + this.passwordHash = passwordHash; + } + // Helper method to extract the file extension private String getFileExtension(String fileName) { int lastDotIndex = fileName.lastIndexOf('.'); @@ -107,6 +116,24 @@ private String calculateFileHash(File file) throws IOException { throw new RuntimeException("MD5 algorithm not found.", e); } } + + //Helper method to Hash Password + public static String hashPassword(String password) { + if (password == null || password.isEmpty()) { + return null; + } + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + byte[] hashBytes = md.digest(password.getBytes()); + StringBuilder sb = new StringBuilder(); + for (byte b : hashBytes) { + sb.append(String.format("%02x", b)); + } + return sb.toString(); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("SHA-256 algorithm not found.", e); + } + } // toString method for easy debugging @Override diff --git a/src/discovery/Handshake.java b/src/discovery/Handshake.java index 0399247..e5c79dd 100644 --- a/src/discovery/Handshake.java +++ b/src/discovery/Handshake.java @@ -38,28 +38,54 @@ public static void start(int port, Node c) { FileResponse res; if (HashtoFD.containsKey(req.FileData.getFileHash())) { - res = new FileResponse(req.RequestingNode, client, true, Handshake.HashtoFD.get(req.FileData.getFileHash())); + FileData storedFile = Handshake.HashtoFD.get(req.FileData.getFileHash()); - UserExperience.printStatus("File found, sending response..."); - ObjectTransfer.sendObject(socket, res); + // Password Verification + boolean passwordValid = true; + if (storedFile.getPasswordHash() != null) { + // File is password protected + String attemptHash = FileData.hashPassword(req.passwordAttempt); + passwordValid = storedFile.getPasswordHash().equals(attemptHash); + + if (passwordValid) { + UserExperience.printSuccess("Password verified"); + } else { + UserExperience.printWarning("Invalid password"); + } + } - obj = ObjectTransfer.receiveObject(socket); - TransferRequest treq = (TransferRequest)obj; - TransferResponse tres = new TransferResponse(treq.RequestingNode, client, treq.Port, true); - ObjectTransfer.sendObject(socket, tres); - - socket.close(); - - UserExperience.printSeparator(); - UserExperience.printStatus("Starting file transfer to " + req.RequestingNode.getPeerIP()); - - ConnectionHandlerSequential.sendFile( - tres.RequestingNode.getPeerIP(), - tres.Port, - Handshake.HashtoPath.get(treq.Fd.getFileHash()), - req.pub - ); + if (passwordValid) { + // Password is correct or no password required - proceed with transfer + res = new FileResponse(req.RequestingNode, client, true, storedFile); + + UserExperience.printStatus("File found, sending response..."); + ObjectTransfer.sendObject(socket, res); + + obj = ObjectTransfer.receiveObject(socket); + TransferRequest treq = (TransferRequest)obj; + + TransferResponse tres = new TransferResponse(treq.RequestingNode, client, treq.Port, true); + ObjectTransfer.sendObject(socket, tres); + + socket.close(); + + UserExperience.printSeparator(); + UserExperience.printStatus("Starting file transfer to " + req.RequestingNode.getPeerIP()); + + ConnectionHandlerSequential.sendFile( + tres.RequestingNode.getPeerIP(), + tres.Port, + Handshake.HashtoPath.get(treq.Fd.getFileHash()), + req.pub + ); + } else { + // PASSWORD INCORRECT + res = new FileResponse(req.RequestingNode, client, false, storedFile); + ObjectTransfer.sendObject(socket, res); + socket.close(); + UserExperience.printSeparator(); + } } } catch (IOException | ClassNotFoundException e) { @@ -79,6 +105,13 @@ public static void registerFile(FileData f, String path) { UserExperience.printStatus("Hash: " + f.getFileHash()); UserExperience.printStatus("Size: " + UserExperience.formatBytes(f.getFileSize())); + //SHOW PASSWORD PROTECTION STATUS + if (f.getPasswordHash() != null) { + UserExperience.printStatus("Security: Password protected"); + } else { + UserExperience.printStatus("Security: Public (no password)"); + } + try { Socket socket = new Socket(central.getPeerIP(), central.getPeerPort()); ObjectTransfer.sendObject(socket, req); diff --git a/src/discovery/messages/FileRequest.java b/src/discovery/messages/FileRequest.java index d64fd5a..c253e50 100644 --- a/src/discovery/messages/FileRequest.java +++ b/src/discovery/messages/FileRequest.java @@ -10,8 +10,11 @@ public class FileRequest implements Serializable{ public FileData FileData; public Node RequestingNode; public PublicKey pub; - public FileRequest(FileData f , Node n){ - this.FileData = f; - this.RequestingNode = n; + public String passwordAttempt; + + public FileRequest(FileData f , Node n , String password) { + this.FileData = f; + this.RequestingNode = n; + this.passwordAttempt = password; } } diff --git a/src/p2p/FileReciever.java b/src/p2p/FileReciever.java index 9f64a9f..a9839db 100644 --- a/src/p2p/FileReciever.java +++ b/src/p2p/FileReciever.java @@ -17,7 +17,8 @@ public class FileReciever { - public static void downloadFile(String fileHash, Node CentralRegistry) { + // Added password parameter + public static void downloadFile(String fileHash, Node CentralRegistry, String password) { UserExperience.printSeparator(); UserExperience.printStage(TransferStage.CONNECTING); @@ -48,7 +49,8 @@ public static void downloadFile(String fileHash, Node CentralRegistry) { UserExperience.printStatus("Attempting download from peer " + (i+1) + "/" + res.peers.length); UserExperience.printStatus("Peer: " + potentialPeer.getPeerIP() + ":" + potentialPeer.getPeerPort()); - if (FileReciever.downloadFromPeer(potentialPeer, file)) { + // Pass password to downloadFromPeer + if (FileReciever.downloadFromPeer(potentialPeer, file, password)) { UserExperience.printSuccess("Download completed successfully!"); downloaded = true; break; @@ -73,9 +75,11 @@ public static void downloadFile(String fileHash, Node CentralRegistry) { } } - public static boolean downloadFromPeer(Node peer, FileData f) { - Node two = Handshake.getClient(); - FileRequest req = new FileRequest(f, two); + // Added password parameter + public static boolean downloadFromPeer(Node peer, FileData f, String password) { + Node two = Handshake.getClient(); + // Pass password in FileRequest constructor + FileRequest req = new FileRequest(f, two, password); try { UserExperience.printStage(TransferStage.NEGOTIATING); @@ -93,6 +97,14 @@ public static boolean downloadFromPeer(Node peer, FileData f) { Object obj = ObjectTransfer.receiveObject(socket); FileResponse res = (FileResponse)obj; + + // Check if rejected due to wrong password + if (!res.response) { + UserExperience.printWarning("Access denied - Invalid password"); + socket.close(); + return false; + } + String fileName = res.file.getFileName(); UserExperience.printSuccess("Peer accepted request for: " + fileName); diff --git a/src/testing/FileTesting.java b/src/testing/FileTesting.java index 35e71e9..15d4ba8 100644 --- a/src/testing/FileTesting.java +++ b/src/testing/FileTesting.java @@ -85,6 +85,8 @@ public static void senderThread(String []files , Thread recieverThread) { t.start(); //this thread line will be started for each of the peer for(String filePath : files) { FileData f = new FileData(filePath); + // Explicitly set no password + f.setPasswordHash(null); // No password for tests Handshake.registerFile(f , filePath); } recieverThread.start(); @@ -97,16 +99,30 @@ public static void senderThread(String []files , Thread recieverThread) { public static void recieverThread(String []hashes) { Node client = new Node(); - client.setPeerIP(SenderIP); - client.setPeerPort(SenderPort); + client.setPeerIP(RecieverIP); // FIXED: Was SenderIP, should be RecieverIP *** + client.setPeerPort(RecieverPort); // FIXED: Was SenderPort, should be RecieverPort *** Node central = new Node(); central.setPeerIP(CentralIP); central.setPeerPort(CentralPort); + // Initialize Handshake for receiver + Handshake.setClient(client); + Handshake.setCentralRegistry(central); + Thread t = new Thread(() -> Handshake.start(client.getPeerPort() , client)); + t.start(); + + // Small delay to ensure receiver is ready + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + for(String hash : hashes) { - FileReciever.downloadFile(hash, central); + // Pass null password for test downloads + FileReciever.downloadFile(hash, central, null); } } -} +} \ No newline at end of file